diff --git a/.circleci/config2.yml b/.circleci/config2.yml
index d33307445..3b0294168 100644
--- a/.circleci/config2.yml
+++ b/.circleci/config2.yml
@@ -121,6 +121,7 @@ commands:
TOOLCHAIN_OPTION="--toolchain clang"
elif [ << parameters.toolchain >> == arm-iar ]; then
TOOLCHAIN_OPTION="--toolchain iar"
+ echo IAR_LMS_CLOUD_URL=$IAR_LMS_CLOUD_URL
iccarm --version
elif [ << parameters.toolchain >> == arm-gcc ]; then
TOOLCHAIN_OPTION="--toolchain gcc"
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 355b6b5c4..547763bd8 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -111,6 +111,7 @@ jobs:
# ---------------------------------------
# Build IAR on HFP self-hosted
+ # Since IAR Token secret is not passed to forked PR, only build on PR from the same repo
# ---------------------------------------
arm-iar:
if: github.repository_owner == 'hathach' && github.event_name == 'push'
@@ -118,6 +119,7 @@ jobs:
runs-on: [self-hosted, Linux, X64, hifiphile]
env:
BUILD_ARGS: ${{ join(fromJSON(needs.set-matrix.outputs.json)['arm-iar'], ' ') }}
+ IAR_LMS_CLOUD_URL: ${{ vars.IAR_LMS_CLOUD_URL }}
IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }}
steps:
- name: Clean workspace
@@ -127,7 +129,9 @@ jobs:
mkdir -p "${{ github.workspace }}"
- name: Toolchain version
- run: iccarm --version
+ run: |
+ echo IAR_LMS_CLOUD_URL=$IAR_LMS_CLOUD_URL
+ iccarm --version
- name: Checkout TinyUSB
uses: actions/checkout@v4
diff --git a/.github/workflows/hil_test.yml b/.github/workflows/hil_test.yml
index 3f32bdb5d..c890933ec 100644
--- a/.github/workflows/hil_test.yml
+++ b/.github/workflows/hil_test.yml
@@ -90,11 +90,13 @@ jobs:
# ---------------------------------------
# Hardware in the loop (HIL)
# self-hosted by HFP, build with IAR toolchain, for attached hardware checkout test/hil/hfp.json
+ # Since IAR Token secret is not passed to forked PR, only build on PR from the same repo
# ---------------------------------------
hil-hfp:
- if: github.repository_owner == 'hathach'
+ if: github.repository_owner == 'hathach' && github.event.pull_request.head.repo.fork == false
runs-on: [self-hosted, Linux, X64, hifiphile]
env:
+ IAR_LMS_CLOUD_URL: ${{ vars.IAR_LMS_CLOUD_URL }}
IAR_LMS_BEARER_TOKEN: ${{ secrets.IAR_LMS_BEARER_TOKEN }}
steps:
- name: Clean workspace
@@ -104,7 +106,9 @@ jobs:
mkdir -p "${{ github.workspace }}"
- name: Toolchain version
- run: iccarm --version
+ run: |
+ echo IAR_LMS_CLOUD_URL=$IAR_LMS_CLOUD_URL
+ iccarm --version
- name: Checkout TinyUSB
uses: actions/checkout@v4
diff --git a/.gitignore b/.gitignore
index 010b5c9ed..5638a09db 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,14 @@ latex
*.jlink
*.emSession
*.ninja*
+*.eww
+*.ewp
+*.ewt
+*.ewd
+*.hex
+cmake_install.cmake
+CMakeCache.txt
+settings/
.settings/
.vscode/
.gdb_history
@@ -37,4 +45,10 @@ cmake-build-*
sdkconfig
.PVS-Studio
.vscode/
-build/
+build
+CMakeFiles
+Debug
+RelWithDebInfo
+Release
+BrowseInfo
+.cmake_build
diff --git a/.idea/cmake.xml b/.idea/cmake.xml
index a792b1a05..7365e13a8 100644
--- a/.idea/cmake.xml
+++ b/.idea/cmake.xml
@@ -12,6 +12,8 @@
+
+
@@ -80,14 +82,14 @@
-
+
-
-
+
+
diff --git a/.idea/debugServers/rp2040.xml b/.idea/debugServers/rp2040.xml
new file mode 100644
index 000000000..f451611f3
--- /dev/null
+++ b/.idea/debugServers/rp2040.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/debugServers/rp2350.xml b/.idea/debugServers/rp2350.xml
new file mode 100644
index 000000000..5e092f3c4
--- /dev/null
+++ b/.idea/debugServers/rp2350.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/debugServers/rt1060.xml b/.idea/debugServers/rt1060.xml
new file mode 100644
index 000000000..3325cc81f
--- /dev/null
+++ b/.idea/debugServers/rt1060.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/debugServers/rt1064.xml b/.idea/debugServers/rt1064.xml
new file mode 100644
index 000000000..4dc38ef63
--- /dev/null
+++ b/.idea/debugServers/rt1064.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/debugServers/sam21.xml b/.idea/debugServers/sam21.xml
new file mode 100644
index 000000000..d8763b33b
--- /dev/null
+++ b/.idea/debugServers/sam21.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/debugServers/sam51.xml b/.idea/debugServers/sam51.xml
new file mode 100644
index 000000000..0d15ff856
--- /dev/null
+++ b/.idea/debugServers/sam51.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 94a25f7f4..d44b5516f 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -2,5 +2,6 @@
+
\ No newline at end of file
diff --git a/README.rst b/README.rst
index e4ad91e47..efbfa354b 100644
--- a/README.rst
+++ b/README.rst
@@ -15,10 +15,7 @@ TinyUSB Project
.. figure:: docs/assets/logo.svg
:alt: TinyUSB
-TinyUSB is an open-source cross-platform USB Host/Device stack for
-embedded system, designed to be memory-safe with no dynamic allocation
-and thread-safe with all interrupt events are deferred then handled in
-the non-ISR task function. Check out the online `documentation `__ for more details.
+TinyUSB is an open-source cross-platform USB Host/Device stack for embedded system, designed to be memory-safe with no dynamic allocation and thread-safe with all interrupt events are deferred then handled in the non-ISR task function. Check out the online `documentation `__ for more details.
.. figure:: docs/assets/stack.svg
:width: 500px
@@ -32,7 +29,7 @@ the non-ISR task function. Check out the online `documentation `_ for information about using TinyUSB and how it is implemented.
-Check out `Getting Started`_ guide for adding TinyUSB to your project or building the examples. If you are new to TinyUSB, we recommend starting with the `cdc_msc` example. There is a handful of `Supported Boards`_ that should work out of the box.
+Check out `Getting Started`_ guide for adding TinyUSB to your project or building the examples. If you are new to TinyUSB, we recommend starting with the ``cdc_msc`` example. There is a handful of `Supported Boards`_ that should work out of the box.
We use `GitHub Discussions `_ as our forum. It is a great place to ask questions and advice from the community or to discuss your TinyUSB-based projects.
@@ -69,7 +66,7 @@ Supports multiple device configurations by dynamically changing USB descriptors,
- Vendor-specific class support with generic In & Out endpoints. Can be used with MS OS 2.0 compatible descriptor to load winUSB driver without INF file.
- `WebUSB `__ with vendor-specific class
-If you have a special requirement, `usbd_app_driver_get_cb()` can be used to write your own class driver without modifying the stack. Here is how the RPi team added their reset interface `raspberrypi/pico-sdk#197 `_
+If you have a special requirement, ``usbd_app_driver_get_cb()`` can be used to write your own class driver without modifying the stack. Here is how the RPi team added their reset interface `raspberrypi/pico-sdk#197 `_
Host Stack
==========
@@ -80,7 +77,7 @@ Host Stack
- Vendor serial over USB: FTDI, CP210x, CH34x
- Hub with multiple-level support
-Similar to the Device Stack, if you have a special requirement, `usbh_app_driver_get_cb()` can be used to write your own class driver without modifying the stack.
+Similar to the Device Stack, if you have a special requirement, ``usbh_app_driver_get_cb()`` can be used to write your own class driver without modifying the stack.
Power Delivery Stack
====================
diff --git a/docs/contributing/code_of_conduct.rst b/docs/contributing/code_of_conduct.rst
deleted file mode 120000
index fb1859c75..000000000
--- a/docs/contributing/code_of_conduct.rst
+++ /dev/null
@@ -1 +0,0 @@
-.. include:: ../../CODE_OF_CONDUCT.rst
\ No newline at end of file
diff --git a/docs/contributing/code_of_conduct.rst b/docs/contributing/code_of_conduct.rst
new file mode 100644
index 000000000..fb1859c75
--- /dev/null
+++ b/docs/contributing/code_of_conduct.rst
@@ -0,0 +1 @@
+.. include:: ../../CODE_OF_CONDUCT.rst
\ No newline at end of file
diff --git a/docs/contributing/porting.rst b/docs/contributing/porting.rst
index f81d98782..c3076354c 100644
--- a/docs/contributing/porting.rst
+++ b/docs/contributing/porting.rst
@@ -9,7 +9,7 @@ data transactions on different endpoints. Porting is the process of adding low-l
the rest of the common stack. Once the low-level is implemented, it is very easy to add USB support
for the microcontroller to other projects, especially those already using TinyUSB such as CircuitPython.
-Below are instructions on how to get the cdc_msc device example running on a new microcontroller. Doing so includes adding the common code necessary for other uses while minimizing other extra code. Whenever you see a phrase or word in <> it should be replaced.
+Below are instructions on how to get the cdc_msc device example running on a new microcontroller. Doing so includes adding the common code necessary for other uses while minimizing other extra code. Whenever you see a phrase or word in ``<>`` it should be replaced.
Register defs
-------------
@@ -18,25 +18,27 @@ The first step to adding support is including the register definitions and start
microcontroller in TinyUSB. We write the TinyUSB implementation against these structs instead of higher level functions to keep the code small and to prevent function name collisions in linking of larger projects. For ARM microcontrollers this is the CMSIS definitions. They should be
placed in the ``hw/mcu//`` directory.
-Once this is done, create a directory in ``hw/bsp/`` for the specific board you are using to test the code. (Duplicating an existing board's directory is the best way to get started.) The board should be a readily available development board so that others can also test.
+Once this is done, create a directory in ``hw/bsp/`` for the specific board you are using to test the code (duplicating an existing board's directory is the best way to get started). The board should be a readily available development board so that others can also test.
Build
-----
Now that those directories are in place, we can start our iteration process to get the example building successfully. To build, run from the root of TinyUSB:
-``make -C examples/device/cdc_msc BOARD=``
+.. code-block:: bash
-Unless, you've read ahead, this will fail miserably. Now, lets get it to fail less by updating the files in the board directory. The code in the board's directory is responsible for setting up the microcontroller's clocks and pins so that USB works. TinyUSB itself only operates on the USB peripheral. The board directory also includes information what files are needed to build the example.
+ make -C examples/device/cdc_msc BOARD=
-One of the first things to change is the ``-DCFG_TUSB_MCU`` cflag in the ``board.mk`` file. This is used to tell TinyUSB what platform is being built. So, add an entry to ``src/tusb_option.h`` and update the CFLAG to match.
+Unless you've read ahead, this will fail miserably. Now, lets get it to fail less by updating the files in the board directory. The code in the board's directory is responsible for setting up the microcontroller's clocks and pins so that USB works. TinyUSB itself only operates on the USB peripheral. The board directory also includes information what files are needed to build the example.
-Update ``board.mk``\ 's VENDOR and CHIP_FAMILY values when creating the directory for the struct files. Duplicate one of the other sources from ``src/portable`` into ``src/portable//`` and delete all of the implementation internals. We'll cover what everything there does later. For now, get it compiling.
+One of the first things to change is the ``-DCFG_TUSB_MCU`` C flag in the ``board.mk`` file. This is used to tell TinyUSB what platform is being built. So, add an entry to ``src/tusb_option.h`` and update the ``CFLAGS`` to match.
+
+Update ``board.mk``'s VENDOR and CHIP_FAMILY values when creating the directory for the struct files. Duplicate one of the other sources from ``src/portable`` into ``src/portable//`` and delete all of the implementation internals. We'll cover what everything there does later. For now, get it compiling.
Implementation
--------------
-At this point you should get an error due to an implementation issue and hopefully the build is setup for the new MCU. You will still need to modify the ``board.mk`` to include specific CFLAGS, the linker script, linker flags, source files, include directories. All file paths are relative to the top of the TinyUSB repo.
+At this point you should get an error due to an implementation issue and hopefully the build is setup for the new MCU. You will still need to modify the ``board.mk`` to include specific ``CFLAGS``, the linker script, linker flags, source files, include directories. All file paths are relative to the top of the TinyUSB repo.
Board Support (BSP)
^^^^^^^^^^^^^^^^^^^
@@ -45,17 +47,17 @@ The board support code is only used for self-contained examples and testing. It
It is located in ``hw/bsp//board_.c``.
-board_init
-~~~~~~~~~~
+``board_init()``
+~~~~~~~~~~~~~~~~
-``board_init`` is responsible for starting the MCU, setting up the USB clock and USB pins. It is also responsible for initializing LED pins.
+``board_init()`` is responsible for starting the MCU, setting up the USB clock and USB pins. It is also responsible for initializing LED pins.
One useful clock debugging technique is to set up a PWM output at a known value such as 500hz based on the USB clock so that you can verify it is correct with a logic probe or oscilloscope.
Setup your USB in a crystal-less mode when available. That makes the code easier to port across boards.
-board_led_write
-~~~~~~~~~~~~~~~
+``board_led_write()``
+~~~~~~~~~~~~~~~~~~~~~
Feel free to skip this until you want to verify your demo code is running. To implement, set the pin corresponding to the led to output a value that lights the LED when ``state`` is true.
@@ -64,48 +66,48 @@ OS Abstraction Layer (OSAL)
The OS Abstraction Layer is responsible for providing basic data structures for TinyUSB that may allow for concurrency when used with an RTOS. Without an RTOS it simply handles concurrency issues between the main code and interrupts. The code is almost entirely agnostic of MCU and lives in ``src/osal``.
-In RTOS configurations, tud_task()/tuh_task() blocks behind a synchronization structure when the event queue is empty, so that the scheduler may give the CPU to a different task. To take advantage of the library's capability to yield the CPU when there are no actionable USB device events, ensure that the `CFG_TUSB_OS` symbol is defined, e.g `OPT_OS_FREERTOS` enables the FreeRTOS scheduler to schedule other threads than that which calls `tud_task()/tuh_task()`.
+In RTOS configurations, ``tud_task()``/``tuh_task()`` blocks behind a synchronization structure when the event queue is empty, so that the scheduler may give the CPU to a different task. To take advantage of the library's capability to yield the CPU when there are no actionable USB device events, ensure that the ``CFG_TUSB_OS`` symbol is defined, e.g ``OPT_OS_FREERTOS`` enables the FreeRTOS scheduler to schedule other threads than that which calls ``tud_task()``/``tuh_task()``.
Device API
^^^^^^^^^^
-After the USB device is setup, the USB device code works by processing events on the main thread (by calling ``tud_task``\ ). These events are queued by the USB interrupt handler. So, there are three parts to the device low-level API: device setup, endpoint setup and interrupt processing.
+After the USB device is setup, the USB device code works by processing events on the main thread (by calling ``tud_task()``). These events are queued by the USB interrupt handler. So, there are three parts to the device low-level API: device setup, endpoint setup and interrupt processing.
All of the code for the low-level device API is in ``src/portable///dcd_.c``.
Device Setup
~~~~~~~~~~~~
-dcd_init
-""""""""
+``dcd_init()``
+""""""""""""""
Initializes the USB peripheral for device mode and enables it.
This function should enable internal D+/D- pull-up for enumeration.
-dcd_int_enable / dcd_int_disable
-""""""""""""""""""""""""""""""""
+``dcd_int_enable()`` / ``dcd_int_disable()``
+""""""""""""""""""""""""""""""""""""""""""""
Enables or disables the USB device interrupt(s). May be used to prevent concurrency issues when mutating data structures shared between main code and the interrupt handler.
-dcd_int_handler
-"""""""""""""""
+``dcd_int_handler()``
+"""""""""""""""""""""
Processes all the hardware generated events e.g Bus reset, new data packet from host etc ... It will be called by application in the MCU USB interrupt handler.
-dcd_set_address
-"""""""""""""""
+``dcd_set_address()``
+"""""""""""""""""""""
Called when the device is given a new bus address.
If your peripheral automatically changes address during enumeration (like the nrf52) you may leave this empty and also no queue an event for the corresponding SETUP packet.
-dcd_remote_wakeup
-"""""""""""""""""
+``dcd_remote_wakeup()``
+"""""""""""""""""""""""
Called to remote wake up host when suspended (e.g hid keyboard)
-dcd_connect / dcd_disconnect
-""""""""""""""""""""""""""""
+``dcd_connect()`` / ``dcd_disconnect()``
+""""""""""""""""""""""""""""""""""""""""
Connect or disconnect the data-line pull-up resistor. Define only if MCU has an internal pull-up. (BSP may define for MCU without internal pull-up.)
@@ -114,8 +116,8 @@ Special events
You must let TinyUSB know when certain events occur so that it can continue its work. There are a few methods you can call to queue events for TinyUSB to process.
-dcd_event_bus_signal
-""""""""""""""""""""
+``dcd_event_bus_signal()``
+""""""""""""""""""""""""""
There are a number of events that your peripheral may communicate about the state of the bus. Here is an overview of what they are. Events in **BOLD** must be provided for TinyUSB to work.
@@ -125,51 +127,51 @@ There are a number of events that your peripheral may communicate about the stat
Calls to this look like:
-.. code-block::
+.. code-block:: c
dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true);
-The first ``0`` is the USB peripheral number. Statically saying 0 is common for single USB device MCUs.
+The first ``0`` is the USB peripheral number. Statically saying ``0`` is common for single USB device MCUs.
The ``true`` indicates the call is from an interrupt handler and will always be the case when porting in this way.
-dcd_setup_received
-""""""""""""""""""
+``dcd_setup_received()``
+""""""""""""""""""""""""
SETUP packets are a special type of transaction that can occur at any time on the control endpoint, numbered ``0``. Since they are unique, most peripherals have special handling for them. Their data is always 8 bytes in length as well.
Calls to this look like:
-.. code-block::
+.. code-block:: c
dcd_event_setup_received(0, setup, true);
-As before with ``dcd_event_bus_signal`` the first argument is the USB peripheral number and the third is true to signal its being called from an interrupt handler. The middle argument is byte array of length 8 with the contents of the SETUP packet. It can be stack allocated because it is copied into the queue.
+As before with ``dcd_event_bus_signal()`` the first argument is the USB peripheral number and the third is true to signal its being called from an interrupt handler. The middle argument is byte array of length 8 with the contents of the SETUP packet. It can be stack allocated because it is copied into the queue.
Endpoints
~~~~~~~~~
Endpoints are the core of the USB data transfer process. They come in a few forms such as control, isochronous, bulk, and interrupt. We won't cover the details here except with some caveats in open below. In general, data is transferred by setting up a buffer of a given length to be transferred on a given endpoint address and then waiting for an interrupt to signal that the transfer is finished. Further details below.
-Endpoints within USB have an address which encodes both the number and direction of an endpoint. TinyUSB provides ``tu_edpt_number`` and ``tu_edpt_dir`` to unpack this data from the address. Here is a snippet that does it.
+Endpoints within USB have an address which encodes both the number and direction of an endpoint. TinyUSB provides ``tu_edpt_number()`` and ``tu_edpt_dir()`` to unpack this data from the address. Here is a snippet that does it.
-.. code-block::
+.. code-block:: c
uint8_t epnum = tu_edpt_number(ep_addr);
uint8_t dir = tu_edpt_dir(ep_addr);
-dcd_edpt_open
-"""""""""""""
+``dcd_edpt_open()``
+"""""""""""""""""""
Opening an endpoint is done for all non-control endpoints once the host picks a configuration that the device should use. At this point, the endpoint should be enabled in the peripheral and configured to match the endpoint descriptor. Pay special attention to the direction of the endpoint you can get from the helper methods above. It will likely change what registers you are setting.
Also make sure to enable endpoint specific interrupts.
-dcd_edpt_close
-""""""""""""""
+``dcd_edpt_close()``
+""""""""""""""""""""
Close an endpoint. his function is used for implementing alternate settings.
@@ -177,10 +179,10 @@ After calling this, the device should not respond to any packets directed toward
Implementation is optional. Must be called from the USB task. Interrupts could be disabled or enabled during the call.
-dcd_edpt_xfer
-"""""""""""""
+``dcd_edpt_xfer()``
+"""""""""""""""""""
-``dcd_edpt_xfer`` is responsible for configuring the peripheral to send or receive data from the host. "xfer" is short for "transfer". **This is one of the core methods you must implement for TinyUSB to work (one other is the interrupt handler).** Data from the host is the OUT direction and data to the host is IN. It is used for all endpoints including the control endpoint 0. Make sure to handle the zero-length packet STATUS packet on endpoint 0 correctly. It may be a special transaction to the peripheral.
+``dcd_edpt_xfer()`` is responsible for configuring the peripheral to send or receive data from the host. "xfer" is short for "transfer". **This is one of the core methods you must implement for TinyUSB to work (one other is the interrupt handler).** Data from the host is the OUT direction and data to the host is IN. It is used for all endpoints including the control endpoint 0. Make sure to handle the zero-length packet STATUS packet on endpoint 0 correctly. It may be a special transaction to the peripheral.
Besides that, all other transactions are relatively straight-forward. The endpoint address provides the endpoint
number and direction which usually determines where to write the buffer info. The buffer and its length are usually
@@ -195,21 +197,21 @@ Others (like the nRF52) may need each USB packet queued individually. To make th
some state for yourself and queue up an intermediate USB packet from the interrupt handler.
Once the transaction is going, the interrupt handler will notify TinyUSB of transfer completion.
-During transmission, the IN data buffer is guaranteed to remain unchanged in memory until the ``dcd_xfer_complete`` function is called.
+During transmission, the IN data buffer is guaranteed to remain unchanged in memory until the ``dcd_xfer_complete()`` function is called.
-The dcd_edpt_xfer function must never add zero-length-packets (ZLP) on its own to a transfer. If a ZLP is required,
-then it must be explicitly sent by the stack calling dcd_edpt_xfer(), by calling dcd_edpt_xfer() a second time with len=0.
+The ``dcd_edpt_xfer()`` function must never add zero-length-packets (ZLP) on its own to a transfer. If a ZLP is required,
+then it must be explicitly sent by the stack calling ``dcd_edpt_xfer()``, by calling ``dcd_edpt_xfer()`` a second time with len=0.
For control transfers, this is automatically done in ``usbd_control.c``.
-At the moment, only a single buffer can be transmitted at once. There is no provision for double-buffering. new dcd_edpt_xfer() will not
-be called again on the same endpoint address until the driver calls dcd_xfer_complete() (except in cases of USB resets).
+At the moment, only a single buffer can be transmitted at once. There is no provision for double-buffering. new ``dcd_edpt_xfer()`` will not
+be called again on the same endpoint address until the driver calls ``dcd_xfer_complete()`` (except in cases of USB resets).
-dcd_xfer_complete
-"""""""""""""""""
+``dcd_xfer_complete()``
+"""""""""""""""""""""""
-Once a transfer completes you must call dcd_xfer_complete from the USB interrupt handler to let TinyUSB know that a transaction has completed. Here is a sample call:
+Once a transfer completes you must call ``dcd_xfer_complete()`` from the USB interrupt handler to let TinyUSB know that a transaction has completed. Here is a sample call:
-.. code-block::
+.. code-block:: c
dcd_event_xfer_complete(0, ep_addr, xfer->actual_len, XFER_RESULT_SUCCESS, true);
@@ -219,23 +221,23 @@ The arguments are:
* the USB peripheral number
* the endpoint address
-* the actual length of the transfer. (OUT transfers may be smaller than the buffer given in ``dcd_edpt_xfer``\ )
+* the actual length of the transfer. (OUT transfers may be smaller than the buffer given in ``dcd_edpt_xfer()``)
* the result of the transfer. Failure isn't handled yet.
* ``true`` to note the call is from an interrupt handler.
-dcd_edpt_stall / dcd_edpt_clear_stall
-"""""""""""""""""""""""""""""""""""""
+``dcd_edpt_stall()`` / ``dcd_edpt_clear_stall()``
+"""""""""""""""""""""""""""""""""""""""""""""""""
-Stalling is one way an endpoint can indicate failure such as when an unsupported command is transmitted. The pair of ``dcd_edpt_stall``\ , ``dcd_edpt_clear_stall`` help manage the stall state of all endpoints.
+Stalling is one way an endpoint can indicate failure such as when an unsupported command is transmitted. The pair of ``dcd_edpt_stall()``, ``dcd_edpt_clear_stall()`` help manage the stall state of all endpoints.
Woohoo!
-------
-At this point you should have everything working! ;-) Of course, you may not write perfect code. Here are some tips and tricks for debugging.
+At this point you should have everything working! 🙂 Of course, you may not write perfect code. Here are some tips and tricks for debugging.
Use `WireShark `_ or `a Beagle `_ to sniff the USB traffic. When things aren't working its likely very early in the USB enumeration process. Figuring out where can help clue in where the issue is. For example:
* If the host sends a SETUP packet and its not ACKed then your USB peripheral probably isn't started correctly.
-* If the peripheral is started correctly but it still didn't work, then verify your usb clock is correct. (You did output a PWM based on it right? ;-) )
-* If the SETUP packet is ACKed but nothing is sent back then you interrupt handler isn't queueing the setup packet correctly. (Also, if you are using your own code instead of an example ``tud_task`` may not be called.) If that's OK, the ``dcd_xfer_complete`` may not be setting up the next transaction correctly.
+* If the peripheral is started correctly but it still didn't work, then verify your usb clock is correct. (You did output a PWM based on it right? 🙂)
+* If the SETUP packet is ACKed but nothing is sent back then you interrupt handler isn't queueing the setup packet correctly. (Also, if you are using your own code instead of an example ``tud_task()`` may not be called.) If that's OK, the ``dcd_xfer_complete()`` may not be setting up the next transaction correctly.
diff --git a/docs/info/changelog.rst b/docs/info/changelog.rst
index 0a34c0842..6024bb9e3 100644
--- a/docs/info/changelog.rst
+++ b/docs/info/changelog.rst
@@ -15,12 +15,12 @@ General
- Better support dcache, make sure all usb-transferred buffer are cache line aligned and occupy full cache line
- Build ARM IAR with CircleCI
-- Improve HIL with dual/host_info_to_device_cdc optional for pico/pico2, enable dwc2 dma test
+- Improve HIL with `dual/host_info_to_device_cdc`` optional for pico/pico2, enable dwc2 dma test
API Changes
-----------
-- Change signature of ``tusb_init(rhport, tusb_rhport_init_t*)``, tusb_init(void) is now deprecated but still available for backward compatibility
+- Change signature of ``tusb_init(rhport, tusb_rhport_init_t*)``, ``tusb_init(void)`` is now deprecated but still available for backward compatibility
- Add new ``tusb_int_handler(rhport, in_isr)``
- Add time-related APIs: ``tusb_time_millis_api()`` and ``tusb_time_delay_ms_api()`` for non-RTOS, required for some ports/configuration
- New configuration macros:
@@ -37,17 +37,17 @@ Controller Driver (DCD & HCD)
- Add DMA support for both device and host controller
- Add host driver support including: full/high speed, control/bulk/interrupt (CBI) transfer, split CBI i.e FS/LS attached via highspeed hub, hub support
-- RP2: implement dcd_edpt_iso_alloc() and dcd_edpt_iso_activate() for isochronous endpoint
+- RP2: implement ``dcd_edpt_iso_alloc()`` and ``dcd_edpt_iso_activate()`` for isochronous endpoint
- iMXRT1170 support M4 core
Device Stack
------------
- Vendor Fix class reset
-- NCM fix recursions in tud_network_recv_renew()
-- Audio fix align issue of _audiod_fct.alt_setting
+- NCM fix recursions in ``tud_network_recv_renew()``
+- Audio fix align issue of ``_audiod_fct.alt_setting``
- UVC support format frame based
-- Change dcd_dcache_() return type from void to bool
+- Change ``dcd_dcache_()`` return type from void to bool
- HID add Usage Table for Physical Input Device Page (0x0F)
Host Stack
@@ -89,20 +89,20 @@ Controller Driver (DCD & HCD)
- Add support for ch32 usbd e.g ch32v203
- Add support for STM32G4 and STM32U5 microcontrollers.
- Fix h5 (32-bit) errata 2.15.1: Buffer description table update completes after CTR interrupt triggers
- - ISO EP buffer allocation improvements, implement dcd_edpt_close_all()
+ - ISO EP buffer allocation improvements, implement ``dcd_edpt_close_all()``
- Fix ch32v203 race condition and stability issue with
- fix ch32v203 seems to unconditionally accept ZLP on EP0 OUT.
- fix v203 race condition between rx bufsize and RX_STAT which cause PMAOVR, occurs with WRITE10
- - correctly handle setup prepare at dcd_edpt0_status_complete(), which fixes the race condition with windows where we could miss setup packet (setup bit set, but count = 0)
+ - correctly handle setup prepare at ``dcd_edpt0_status_complete()``, which fixes the race condition with windows where we could miss setup packet (setup bit set, but count = 0)
- MAX3421E
- Add support for rp2040, esp32 (c3, c6, h2, etc..)
- - Add hcd_deinit() for max3421
+ - Add ``hcd_deinit()`` for max3421
- Retry NAK handling next frame to reduce CPU and SPI bus usage
- - add cpuctl and pinctl to tuh_configure() option for max3421
+ - add ``cpuctl`` and ``pinctl`` to ``tuh_configure()`` option for max3421
- Implement hcd abort transfer for Max3421
- Properly Handle NAK Response in MAX3421E driver: correctly switch and skip writing to 2 FIFOs when NAK received. Otherwise, the driver may hang in certain conditions.
@@ -114,7 +114,7 @@ Controller Driver (DCD & HCD)
- nRF
- - Fix dcd_edpt_open for iso endpoint
+ - Fix ``dcd_edpt_open()`` for iso endpoint
- Handle ISOOUT CRC errors
- Add compile support with old nordic sdk
- Fix a few race conditions
@@ -141,7 +141,7 @@ Controller Driver (DCD & HCD)
Device Stack
------------
-- Add tud_deinit() and class driver deinit() to deinitialize TinyUSB device stack.
+- Add ``tud_deinit()`` and ``class driver deinit()`` to deinitialize TinyUSB device stack.
- Add support for generic SOF callback.
- Add set address recovery time 2ms per USB spec.
@@ -157,7 +157,7 @@ Device Stack
- CDC
- - Add tud_cdc_configure_fifo() to make RX/TX buffer persistent (not clear when disconnected)
+ - Add ``tud_cdc_configure_fifo()`` to make RX/TX buffer persistent (not clear when disconnected)
- Add missing capability bit for CDC ACM serial break support
- Enhanced CDC class with better handling of large data transmissions.
- Add missing capability bit for CDC ACM serial break support
@@ -175,39 +175,39 @@ Device Stack
- Net
- Rewrite of NCM device driver to improve throughput
- - removed obsolete tud_network_link_state_cb()
+ - removed obsolete ``tud_network_link_state_cb()``
- USBTMC Added notification support
- Vendor
- Migrate to new endpoint stream API, support non-buffered TX/RX
- - Add ZLP for write() when needed
+ - Add ZLP for ``write()`` when needed
- Video
- Enhance UVC descriptors and example
- Video Added support for USB Video Class (UVC) with MJPEG.
- Fix multiple interfaces, add an example of 2ch video capture.
- - Fix race for tud_video_n_streaming check
+ - Fix race for ``tud_video_n_streaming()`` check
Host Stack
----------
-- Added tuh_deinit() to de-initialize TinyUSB host stack.
+- Added ``tuh_deinit()`` to de-initialize TinyUSB host stack.
- Added support for new USB mass storage class APIs.
- Improved error handling and retry mechanisms for unstable devices.
- CDC Serial
- Add support for ch34x
- - Allow to overwrite CFG_TUH_CDC_FTDI/CP210X/CH32X_VID_PID_LIST
+ - Allow to overwrite ``CFG_TUH_CDC_FTDI/CP210X/CH32X_VID_PID_LIST``
- Enhanced stability of CDC-ACM devices during enumeration.
- HID
- - Add tuh_hid_receive_abort()
- - Add tuh_hid_get_report()
+ - Add ``tuh_hid_receive_abort()``
+ - Add ``tuh_hid_get_report()``
- Hub
@@ -224,14 +224,14 @@ Host Stack
- Remove submodules and use python script to manage repo dependencies #1947
- Add CMake support for most families and boards, move build file from tools/ to examples/build_system
- Add ETM trace support with JTrace for nrf52840, nrf5340, mcb1857, stm32h743eval, ra6m5
-- [osal] Make it possible to override the osal_task_delay() in osal_none
+- [osal] Make it possible to override the ``osal_task_delay()`` in osal_none
- Add CDC+UAC2 composite device example
- Enhance Hardware-in-the-loop (HIL) testing with more boards: rp2040, stm32l412nucleo, stm32f746disco, lpcxpresso43s67
Controller Driver (DCD & HCD)
-----------------------------
-- Add new ISO endpoint API: dcd_edpt_iso_alloc() and dcd_edpt_iso_activate()
+- Add new ISO endpoint API: ``dcd_edpt_iso_alloc()`` and ``dcd_edpt_iso_activate()``
- Remove legacy driver st/synopsys
- EHCI
@@ -244,10 +244,10 @@ Controller Driver (DCD & HCD)
- Fix error on EHCI causes xfer error in non-queued qhd which cause memory fault
- Un-roll recursive hub removal with usbh queue
- Fix issue when removing queue head
- - Implement hcd_edpt_abort_xfer()
+ - Implement ``hcd_edpt_abort_xfer()``
- use standard USB complete interrupt instead of custom chipidea async/period interrupt to be more compatible with other ehci implementation
- refactor usb complete & error isr processing, merge, update. Fix EHCI QHD reuses QTD on wrong endpoint
- - Improve bus reset, fix send_setup() not carried out if halted previously
+ - Improve bus reset, fix ``send_setup()`` not carried out if halted previously
- Fix clear qhd halted bit if not caused by STALL protocol to allow for next transfer
- ChipIdea Highspeed
@@ -273,12 +273,12 @@ Controller Driver (DCD & HCD)
- rp2040
- [dcd] Make writes to SIE_CTRL aware of concurrent access
- - [hcd] add hcd_frame_number(), hcd_edpt_abort_xfer() for pio-usb host
+ - [hcd] add ``hcd_frame_number()``, ``hcd_edpt_abort_xfer()`` for pio-usb host
- stm32 fsdev:
- Add STM32L5 support
- - Implement dcd_edpt_iso_alloc() and dcd_edpt_iso_activate()
+ - Implement ``dcd_edpt_iso_alloc()`` and ``dcd_edpt_iso_activate()``
- OHCI
@@ -292,7 +292,7 @@ Controller Driver (DCD & HCD)
Device Stack
------------
-- Add optional hooks tud_event_hook_cb()
+- Add optional hooks ``tud_event_hook_cb()``
- Audio (UAC2)
- Fix feedback EP buffer alignment.
@@ -310,12 +310,12 @@ Device Stack
- MIDI
- - Fix stream_write() always writes system messages to cable 0
+ - Fix ``stream_write()`` always writes system messages to cable 0
- Fix incorrect NOTE_ON, NOTE_OFF definitions
- USBTMC: Fix tmc488 bit order
-- Vendor: fix read()/write() race condition
+- Vendor: fix ``read()``/``write()`` race condition
- Video (UVC)
@@ -326,26 +326,26 @@ Host Stack
- USBH
- - Add new APIs: tuh_interface_set(), tuh_task_event_ready(), tuh_edpt_abort_xfer(), tuh_rhport_reset_bus(), tuh_rhport_is_active()
+ - Add new APIs: ``tuh_interface_set()``, ``tuh_task_event_ready()``, ``tuh_edpt_abort_xfer()``, ``tuh_rhport_reset_bus()``, ``tuh_rhport_is_active()``
- Fix issue when device generate multiple attach/detach/attach when plugging in
- Prefer application callback over built-in driver on transfer complete event
- - Correct hcd_edpt_clear_stall() API signature
+ - Correct ``hcd_edpt_clear_stall()`` API signature
- Separate bus reset delay and contact debouncing delay in enumeration
- - Support usbh_app_driver_get_cb() for application drivers
+ - Support ``usbh_app_driver_get_cb()`` for application drivers
- Fix usbh enumeration removal race condition
- - Add optional hooks tuh_event_hook_cb()
+ - Add optional hooks ``tuh_event_hook_cb()``
- CDC
- - Breaking: change tuh_cdc_itf_get_info() to use tuh_itf_info_t instead of tuh_cdc_info_t
+ - Breaking: change ``tuh_cdc_itf_get_info()`` to use tuh_itf_info_t instead of tuh_cdc_info_t
- Fix cdc host enumeration issue when device does not support line request
- Add support for vendor usb2uart serial: ftdi, cp210x, ch9102f
- - Improve sync control API e.g tuh_cdc_set_control_line_state(), tuh_cdc_set_line_coding()
+ - Improve sync control API e.g ``tuh_cdc_set_control_line_state()``, ``tuh_cdc_set_line_coding()``
- HID
- - Add new APIs tuh_hid_send_report(), tuh_hid_itf_get_info(), tuh_hid_receive_ready(), tuh_hid_send_ready(), tuh_hid_set_default_protocol()
- - Change meaning of CFG_TUH_HID to total number of HID interfaces supported. Previously CFG_TUH_HID is max number of interfaces per device which is rather limited and consume more resources than needed.
+ - Add new APIs ``tuh_hid_send_report()``, ``tuh_hid_itf_get_info()``, ``tuh_hid_receive_ready()``, ``tuh_hid_send_ready()``, ``tuh_hid_set_default_protocol()``
+ - Change meaning of CFG_TUH_HID to total number of HID interfaces supported. Previously ``CFG_TUH_HID`` is max number of interfaces per device which is rather limited and consume more resources than needed.
- HUB
@@ -354,7 +354,7 @@ Host Stack
- MSC
- - Fix bug in tuh_msc_ready()
+ - Fix bug in ``tuh_msc_ready()``
- Fix host msc get maxlun not using aligned section memory
0.15.0
@@ -385,7 +385,7 @@ Controller Driver (DCD & HCD)
- [rp2040]
- [dcd] Implement workaround for Errata 15. This enable SOF when bulk-in endpoint is in use and reduce its bandwidth to only 80%
- - [hcd] Fix shared irq slots filling up when hcd_init() is called multiple times
+ - [hcd] Fix shared irq slots filling up when ``hcd_init()`` is called multiple times
- [hcd] Support host bulk endpoint using hw "interrupt" endpoint. Note speed limit is 64KB/s
- [samd][dcd] Add support for ISO endpoint
@@ -410,12 +410,12 @@ Device Stack
- [HID]
- Add FIDO descriptor template
- - change length in tud_hid_report_complete_cb() from uint8 to uint16
+ - change length in ``tud_hid_report_complete_cb()`` from ``uint8_t`` to ``uint16_t``
- [CDC]
- Fix autoflush for FIFO < MPS
- - Fix tx fifo memory overflown when DTR is not set and tud_cdc_write() is called repeatedly with large enough data
+ - Fix tx fifo memory overflown when DTR is not set and ``tud_cdc_write()`` is called repeatedly with large enough data
- [USBTMC] Fix packet size with highspeed
@@ -423,7 +423,7 @@ Host Stack
----------
- Retry a few times with transfers in enumeration since device can be unstable when starting up
-- [MSC] Rework host masstorage API. Add new **host/msc_file_explorer** example
+- [MSC] Rework host masstorage API. Add new ``host/msc_file_explorer`` example
- [CDC]
- Add support for host cdc
@@ -433,22 +433,22 @@ Host Stack
======
- 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 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.
+ - ``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)
+ - ``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
@@ -469,10 +469,10 @@ Device Stack
- [Audio] Add support for feedback endpoint computation
- - New API tud_audio_feedback_params_cb(), tud_audio_feedback_interval_isr().
+ - 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()
+ - 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
@@ -481,23 +481,23 @@ Device Stack
Host Stack
----------
-- Add new API tuh_configure(rhport, cfg_id, cfg_param) for dynamnic port specific behavior configuration
+- 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`
+ - 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
+ - ``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
======
-- [tu_fifo] Fix locked mutex when full, and return type in peek_n()
+- [tu_fifo] Fix locked mutex when full, and return type in ``peek_n()``
Controller Driver (DCD & HCD)
-----------------------------
@@ -526,7 +526,7 @@ Device Stack
------------
- [Audio] Support disabling feedback format correction (16.16 <-> 10.14 format)
-- [MSC] Add tud_msc_request_sense_cb() callback, change most default sense error to medium not present (0x02, 0x3A, 0x00)
+- [MSC] Add ``tud_msc_request_sense_cb()`` callback, change most default sense error to medium not present (0x02, 0x3A, 0x00)
- [Video] Fix video_capture example fails enumeration when 8FPS
Host Stack
@@ -537,22 +537,22 @@ No notable changes
0.12.0
======
-- add CFG_TUSB_OS_INC_PATH for os include path
+- add ``CFG_TUSB_OS_INC_PATH`` for os include path
Device Controller Driver (DCD)
------------------------------
- Getting device stack to pass USB Compliance Verification test (chapter9, HID, MSC). Ports are tested:
nRF, SAMD 21/51, rp2040, stm32f4, Renesas RX, iMXRT, ESP32-S2/3, Kinetic KL25/32, DA146xx
-- Added dcd_edpt_close_all() for switching configuration
-- [Transdimension] Support dcd_edpt_xfer_fifo() with auto wrap over if fifo buffer is 4K aligned and size is multiple of 4K.
+- Added ``dcd_edpt_close_all()`` for switching configuration
+- [Transdimension] Support ``dcd_edpt_xfer_fifo()`` with auto wrap over if fifo buffer is 4K aligned and size is multiple of 4K.
- [DA146xx] Improve vbus, reset, suspend, resume detection, and remote wakeup.
Device Stack
------------
-- Add new network driver Network Control Model (CDC-NCM), update net_lwip_webserver to work with NCM (need re-configure example)
-- Add new USB Video Class UVC 1.5 driver and video_capture example ((work in progress)
+- Add new network driver Network Control Model (CDC-NCM), update ``net_lwip_webserver`` to work with NCM (need re-configure example)
+- Add new USB Video Class UVC 1.5 driver and video_capture example (work in progress)
- Fix potential buffer overflow for HID, bluetooth drivers
Host Controller Driver (HCD)
@@ -589,13 +589,13 @@ Synopsys
^^^^^^^^
- Fix Synopsys set address bug which could cause re-enumeration failed
-- Fix dcd_synopsys driver integer overflow in HS mode (issue #968)
+- Fix ``dcd_synopsys`` driver integer overflow in HS mode (issue #968)
nRF5x
^^^^^
- Add nRF5x suspend, resume and remote wakeup
-- Fix nRF5x race condition with TASKS_EP0RCVOUT
+- Fix nRF5x race condition with ``TASKS_EP0RCVOUT``
RP2040
^^^^^^
@@ -610,8 +610,8 @@ USBD
^^^^
- Better support big endian mcu
-- Add tuh_inited() and tud_inited(), will separate tusb_init/inited() to tud/tuh init/inited
-- Add dcd_attr.h for defining common controller attribute such as max endpoints
+- Add ``tuh_inited()`` and ``tud_inited()``, will separate ``tusb_init/inited()`` to ``tud/tuh_init/inited()``
+- Add ``dcd_attr.h`` for defining common controller attribute such as max endpoints
Bluetooth
^^^^^^^^^
@@ -621,8 +621,8 @@ Bluetooth
DFU
^^^
-- Enhance DFU implementation to support multiple alternate interface and better support bwPollTimeout
-- Rename CFG_TUD_DFU_MODE to simply CFG_TUD_DFU
+- Enhance DFU implementation to support multiple alternate interface and better support ``bwPollTimeout``
+- Rename ``CFG_TUD_DFU_MODE`` to simply ``CFG_TUD_DFU``
HID
^^^
@@ -647,7 +647,7 @@ Vendor
^^^^^^
- Fix vendor fifo deadlock in certain case
-- Add tud_vendor_n_read_flush
+- Add ``tud_vendor_n_read_flush()``
Host Controller Driver (HCD)
----------------------------
@@ -664,7 +664,7 @@ Host Stack
- Major update and rework most of host stack, still needs more improvement
- Lots of improvement and update in parsing configuration and control
- Rework and major update to HID driver. Will default to enable boot interface if available
-- Separate CFG_TUH_DEVICE_MAX and CFG_TUH_HUB for better management and reduce SRAM usage
+- Separate ``CFG_TUH_DEVICE_MAX`` and ``CFG_TUH_HUB`` for better management and reduce SRAM usage
0.10.1 (2021-06-03)
===================
@@ -676,9 +676,9 @@ Host Controller Driver (HCD)
- Fix rp2040 host driver: incorrect PID with low speed device with max packet size of 8 bytes
- Improve hub driver
-- Remove obsolete hcd_pipe_queue_xfer()/hcd_pipe_xfer()
-- Use hcd_frame_number() instead of micro frame
-- Fix OHCI endpoint address and xferred_bytes in xfer complete event
+- Remove obsolete ``hcd_pipe_queue_xfer()``/``hcd_pipe_xfer()``
+- Use ``hcd_frame_number()`` instead of micro frame
+- Fix OHCI endpoint address and ``xferred_bytes`` in xfer complete event
0.10.0 (2021-05-28)
===================
@@ -697,7 +697,7 @@ Device Controller Driver (DCD)
- Fix build with nRF5340
- Fix build with lpc15 and lpc54
- Fix build with lpc177x_8x
-- STM32 Synopsys: greatly improve Isochronous transfer with edpt_xfer_fifo API
+- STM32 Synopsys: greatly improve Isochronous transfer with ``edpt_xfer_fifo()`` API
- Support LPC55 port1 highspeed
- Add support for Espressif esp32s3
- nRF: fix race condition that could cause drop packet of Bulk OUT transfer
@@ -705,14 +705,14 @@ Device Controller Driver (DCD)
USB Device Driver (USBD)
------------------------
-- Add new (optional) endpoint ADPI usbd_edpt_xfer_fifo
+- Add new (optional) endpoint ADPI ``usbd_edpt_xfer_fifo()``
Device Class Driver
-------------------
CDC
-- [Breaking] tud_cdc_peek(), tud_vendor_peek() no longer support random offset and dropped position parameter.
+- [Breaking] ``tud_cdc_peek()``, ``tud_vendor_peek()`` no longer support random offset and dropped position parameter.
DFU
@@ -724,19 +724,19 @@ HID
- Add more hid keys constant from 0x6B to 0xA4
- [Breaking] rename API
- - HID_PROTOCOL_NONE/KEYBOARD/MOUST to HID_ITF_PROTOCOL_NONE/KEYBOARD/MOUSE
- - tud_hid_boot_mode() to tud_hid_get_protocol()
- - tud_hid_boot_mode_cb() to tud_hid_set_protocol_cb()
+ - ``HID_PROTOCOL_NONE/KEYBOARD/MOUSE`` to ``HID_ITF_PROTOCOL_NONE/KEYBOARD/MOUSE``
+ - ``tud_hid_boot_mode()`` to ``tud_hid_get_protocol()``
+ - ``tud_hid_boot_mode_cb()`` to ``tud_hid_set_protocol_cb()``
MIDI
- Fix MIDI buffer overflow issue
- [Breaking] rename API
- - Rename tud_midi_read() to tud_midi_stream_read()
- - Rename tud_midi_write() to tud_midi_stream_write()
- - Rename tud_midi_receive() to tud_midi_packet_read()
- - Rename tud_midi_send() to tud_midi_packet_write()
+ - Rename ``tud_midi_read()`` to ``tud_midi_stream_read()``
+ - Rename ``tud_midi_write()`` to ``tud_midi_stream_write()``
+ - Rename ``tud_midi_receive()`` to ``tud_midi_packet_read()``
+ - Rename ``tud_midi_send()`` to ``tud_midi_packet_write()``
Host Controller Driver (HCD)
----------------------------
@@ -783,7 +783,7 @@ NXP Transdimention
USB Device Driver (USBD)
^^^^^^^^^^^^^^^^^^^^^^^^
-- Fix issue with status zlp (tud_control_status) is returned by class driver with SET/CLEAR_FEATURE for endpoint.
+- Fix issue with status zlp (``tud_control_status()``) is returned by class driver with SET/CLEAR_FEATURE for endpoint.
- Correct endpoint size check for fullspeed bulk, can be 8, 16, 32, 64
- Ack SET_INTERFACE even if it is not implemented by class driver.
@@ -792,34 +792,34 @@ Device Class Driver
DFU Runtime
-- rename dfu_rt to dfu_runtime for easy reading
+- rename ``dfu_rt()`` to ``dfu_runtime()`` for easy reading
CDC
-- Add tud_cdc_send_break_cb() to support break request
-- Improve CDC receive, minor behavior changes: when tud_cdc_rx_wanted_cb() is invoked wanted_char may not be the last byte in the fifo
+- Add ``tud_cdc_send_break_cb()`` to support break request
+- Improve CDC receive, minor behavior changes: when ``tud_cdc_rx_wanted_cb()`` is invoked wanted_char may not be the last byte in the fifo
HID
- [Breaking] Add itf argument to hid API to support multiple instances, follow API has signature changes
- - tud_hid_descriptor_report_cb()
- - tud_hid_get_report_cb()
- - tud_hid_set_report_cb()
- - tud_hid_boot_mode_cb()
- - tud_hid_set_idle_cb()
+ - ``tud_hid_descriptor_report_cb()``
+ - ``tud_hid_get_report_cb()``
+ - ``tud_hid_set_report_cb()``
+ - ``tud_hid_boot_mode_cb()``
+ - ``tud_hid_set_idle_cb()``
-- Add report complete callback tud_hid_report_complete_cb() API
+- Add report complete callback ``tud_hid_report_complete_cb()`` API
- Add DPad/Hat support for HID Gamepad
- - `TUD_HID_REPORT_DESC_GAMEPAD()` now support 16 buttons, 2 joysticks, 1 hat/dpad
- - Add hid_gamepad_report_t along with `GAMEPAD_BUTTON_` and `GAMEPAD_HAT_` enum
- - Add Gamepad to hid_composite / hid_composite_freertos example
+ - ``TUD_HID_REPORT_DESC_GAMEPAD()`` now support 16 buttons, 2 joysticks, 1 hat/dpad
+ - Add ``hid_gamepad_report_t`` along with ``GAMEPAD_BUTTON_`` and ``GAMEPAD_HAT_`` enum
+ - Add Gamepad to ``hid_composite`` / ``hid_composite_freertos`` example
MIDI
- Fix dropping MIDI sysex message when fifo is full
-- Fix typo in tud_midi_write24(), make example less ambiguous for cable and channel
+- Fix typo in ``tud_midi_write24()``, make example less ambiguous for cable and channel
- Fix incorrect endpoint descriptor length, MIDI v1 use Audio v1 which has 9-byte endpoint descriptor (instead of 7)
Host Stack
@@ -828,14 +828,14 @@ Host Stack
Host Controller Driver (HCD)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-- Add rhport to hcd_init()
+- Add rhport to ``hcd_init()``
- Improve EHCI/OHCI driver abstraction
- Move echi/ohci files to portable/
- - Rename hcd_lpc18_43 to hcd_transdimension
- - Sub hcd API with hcd_ehci_init(), hcd_ehci_register_addr()
+ - Rename ``hcd_lpc18_43`` to ``hcd_transdimension``
+ - Sub hcd API with ``hcd_ehci_init()``, ``hcd_ehci_register_addr()``
-- Update NXP transdimention hcd_init() to reset controller to host mode
+- Update NXP transdimension ``hcd_init()`` to reset controller to host mode
- Ported hcd to rt10xx
@@ -849,20 +849,20 @@ Host Class Driver
MSC
-- Rename tuh_msc_scsi_inquiry() to tuh_msc_inquiry()
-- Rename tuh_msc_mounted_cb/tuh_msc_unmounted_cb to tuh_msc_mount_cb/tuh_msc_unmount_cb to match device stack naming
-- Change tuh_msc_is_busy() to tuh_msc_ready()
-- Add read10 and write10 function: tuh_msc_read10(), tuh_msc_write10()
+- Rename ``tuh_msc_scsi_inquiry()`` to ``tuh_msc_inquiry()``
+- Rename ``tuh_msc_mounted_cb()``/``tuh_msc_unmounted_cb()`` to ``tuh_msc_mount_cb()``/``tuh_msc_unmount_cb()`` to match device stack naming
+- Change ``tuh_msc_is_busy()`` to ``tuh_msc_ready()``
+- Add read10 and write10 function: ``tuh_msc_read10()``, ``tuh_msc_write10()``
- Read_Capacity is invoked as part of enumeration process
-- Add tuh_msc_get_block_count(), tuh_msc_get_block_size()
-- Add CFG_TUH_MSC_MAXLUN (default to 4) to hold lun capacities
+- Add ``tuh_msc_get_block_count()``, ``tuh_msc_get_block_size()``
+- Add ``CFG_TUH_MSC_MAXLUN`` (default to 4) to hold lun capacities
Others
------
- Add basic support for rt-thread OS
- Change zero bitfield length to more explicit padding
-- Build example now fetch required submodules on the fly while running `make` without prio submodule init for mcu drivers
+- Build example now fetch required submodules on the fly while running ``make`` without prior submodule init for mcu drivers
- Update pico-sdk to v1.1.0
**New Boards**
@@ -880,7 +880,7 @@ Device Controller Driver
- Added new device support for Raspberry Pi RP2040
- Added new device support for NXP Kinetis KL25ZXX
-- Use dcd_event_bus_reset() with link speed to replace bus_signal
+- Use ``dcd_event_bus_reset()`` with link speed to replace bus_signal
- ESP32-S2:
- Add bus suspend and wakeup support
@@ -902,8 +902,8 @@ USB Device
**USBD**
- Rework usbd control transfer to have additional stage parameter for setup, data, status
-- Fix tusb_init() return true instead of TUSB_ERROR_NONE
-- Added new API tud_connected() that return true after device got out of bus reset and received the very first setup packet
+- Fix ``tusb_init()`` return true instead of ``TUSB_ERROR_NONE``
+- Added new API ``tud_connected()`` that return true after device got out of bus reset and received the very first setup packet
**Class Driver**
@@ -911,22 +911,22 @@ USB Device
- Allow to transmit data, even if the host does not support control line states i.e set DTR
- HID
- - change default CFG_TUD_HID_EP_BUFSIZE from 16 to 64
+ - change default ``CFG_TUD_HID_EP_BUFSIZE`` from 16 to 64
- MIDI
- Fix midi sysex sending bug
- MSC
- Invoke only scsi complete callback after status transaction is complete.
- - Fix scsi_mode_sense6_t padding, which cause IAR compiler internal error.
+ - Fix ``scsi_mode_sense6_t`` padding, which cause IAR compiler internal error.
- USBTMC
- Change interrupt endpoint example size to 8 instead of 2 for better compatibility with mcu
**Example**
-- Support make from windows cmd.exe
-- Add HID Consumer Control (media keys) to hid_composite & hid_composite_freertos examples
+- Support make from windows ``cmd.exe``
+- Add HID Consumer Control (media keys) to ``hid_composite`` & ``hid_composite_freertos`` examples
USB Host
@@ -967,28 +967,28 @@ Device Controller Driver
- Support multiple usb ports with rhport=1 is highspeed on selected MCUs e.g H743, F23. It is possible to have OTG_HS to run on Fullspeed PHY (e.g lacking external PHY)
- Add ISO transfer, fix odd/even frame
- Fix FIFO flush during stall
- - Implement dcd_edpt_close() API
+ - Implement ``dcd_edpt_close()`` API
- Support F105, F107
- Enhance STM32 fsdev
- Improve dcd fifo allocation
- Fix ISTR race condition
- Support remap USB IRQ on supported MCUs
- - Implement dcd_edpt_close() API
+ - Implement ``dcd_edpt_close()`` API
- Enhance NUC 505: enhance set configure behavior
- Enhance SAMD
- Fix race condition with setup packet
- - Add SAMD11 option `OPT_MCU_SAMD11`
- - Add SAME5x option `OPT_MCU_SAME5X`
+ - Add SAMD11 option ``OPT_MCU_SAMD11``
+ - Add SAME5x option ``OPT_MCU_SAME5X``
- Fix SAMG control data toggle and stall race condition
- Enhance nRF
- - Fix hanged when tud_task() is called within critical section (disabled interrupt)
+ - Fix hanged when ``tud_task()`` is called within critical section (disabled interrupt)
- Fix disconnect bus event not submitted
- - Implement ISO transfer and dcd_edpt_close()
+ - Implement ISO transfer and ``dcd_edpt_close()``
USB Device
@@ -997,26 +997,26 @@ USB Device
**USBD**
- Add new class driver for **Bluetooth HCI** class driver with example can be found in [mynewt-tinyusb-example](https://github.com/hathach/mynewt-tinyusb-example) since it needs mynewt OS to run with.
-- Fix USBD endpoint usage racing condition with `usbd_edpt_claim()/usbd_edpt_release()`
-- Added `tud_task_event_ready()` and `osal_queue_empty()`. This API is needed to check before enter low power mode with WFI/WFE
-- Rename USB IRQ Handler to `dcd_int_handler()`. Application must define IRQ handler in which it calls this API.
-- Add `dcd_connect()` and `dcd_disconnect()` to enable/disable internal pullup on D+/D- on supported MCUs.
-- Add `usbd_edpt_open()`
-- Remove `dcd_set_config()`
-- Add *OPT_OS_CUMSTOM* as hook for application to overwrite and/or add their own OS implementation
+- Fix USBD endpoint usage racing condition with ``usbd_edpt_claim()``/``usbd_edpt_release()``
+- Added ``tud_task_event_ready()`` and ``osal_queue_empty()``. This API is needed to check before enter low power mode with WFI/WFE
+- Rename USB IRQ Handler to ``dcd_int_handler()``. Application must define IRQ handler in which it calls this API.
+- Add ``dcd_connect()`` and ``dcd_disconnect()`` to enable/disable internal pullup on D+/D- on supported MCUs.
+- Add ``usbd_edpt_open()``
+- Remove ``dcd_set_config()``
+- Add ``OPT_OS_CUMSTOM`` as hook for application to overwrite and/or add their own OS implementation
- Support SET_INTERFACE, GET_INTERFACE request
-- Add Logging for debug with optional uart/rtt/swo printf retarget or `CFG_TUSB_DEBUG_PRINTF` hook
+- Add Logging for debug with optional uart/rtt/swo printf retarget or ``CFG_TUSB_DEBUG_PRINTF`` hook
- Add IAR compiler support
-- Support multiple configuration descriptors. `TUD_CONFIG_DESCRIPTOR()` template has extra config_num as 1st argument
-- Improve USB Highspeed support with actual link speed detection with `dcd_event_bus_reset()`
+- Support multiple configuration descriptors. ``TUD_CONFIG_DESCRIPTOR()`` template has extra config_num as 1st argument
+- Improve USB Highspeed support with actual link speed detection with ``dcd_event_bus_reset()``
- Enhance class driver management
- - `usbd_driver_open()` add max length argument, and return length of interface (0 for not supported). Return value is used for finding appropriate driver
- - Add application implemented class driver via `usbd_app_driver_get_cb()`
+ - ``usbd_driver_open()`` add max length argument, and return length of interface (0 for not supported). Return value is used for finding appropriate driver
+ - Add application implemented class driver via ``usbd_app_driver_get_cb()``
- IAD is handled to assign driver id
-- Added `tud_descriptor_device_qualifier_cb()` callback
-- Optimize `tu_fifo` bulk write/read transfer
+- Added ``tud_descriptor_device_qualifier_cb()`` callback
+- Optimize ``tu_fifo`` bulk write/read transfer
- Forward non-std control request to class driver
- Let application handle Microsoft OS 1.0 Descriptors (the 0xEE index string)
- Fix OSAL FreeRTOS yield from ISR
@@ -1028,8 +1028,8 @@ USB Device
- CDC:
- Send zero length packet for end of data when needed
- - Add `tud_cdc_tx_complete_cb()` callback
- - Change tud_cdc_n_write_flush() return number of bytes forced to transfer, and flush when writing enough data to fifo
+ - Add ``tud_cdc_tx_complete_cb()`` callback
+ - Change ``tud_cdc_n_write_flush()`` return number of bytes forced to transfer, and flush when writing enough data to fifo
- MIDI:
- Add packet interface
@@ -1039,10 +1039,10 @@ USB Device
- DFU Runtime: fix response to SET_INTERFACE and DFU_GETSTATUS request
- Rename some configure macro to make it clear that those are used directly for endpoint transfer
- - CFG_TUD_HID_BUFSIZE to CFG_TUD_HID_EP_BUFSIZE
- - CFG_TUD_CDC_EPSIZE to CFG_TUD_CDC_EP_BUFSIZE
- - CFG_TUD_MSC_BUFSIZE to CFG_TUD_MSC_EP_BUFSIZE
- - CFG_TUD_MIDI_EPSIZE to CFG_TUD_MIDI_EP_BUFSIZE
+ - ``CFG_TUD_HID_BUFSIZE`` to ``CFG_TUD_HID_EP_BUFSIZE``
+ - ``CFG_TUD_CDC_EPSIZE`` to ``CFG_TUD_CDC_EP_BUFSIZE``
+ - ``CFG_TUD_MSC_BUFSIZE`` to ``CFG_TUD_MSC_EP_BUFSIZE``
+ - ``CFG_TUD_MIDI_EPSIZE`` to ``CFG_TUD_MIDI_EP_BUFSIZE``
- HID:
- Fix gamepad template descriptor
@@ -1061,15 +1061,15 @@ USB Host
Examples
--------
-- Add new hid_composite_freertos
-- Add new dynamic_configuration to demonstrate how to switch configuration descriptors
-- Add new hid_multiple_interface
+- Add new ``hid_composite_freertos``
+- Add new ``dynamic_configuration`` to demonstrate how to switch configuration descriptors
+- Add new ``hid_multiple_interface``
-- Enhance `net_lwip_webserver` example
+- Enhance ``net_lwip_webserver`` example
- Add multiple configuration: RNDIS for Windows, CDC-ECM for macOS (Linux will work with both)
- - Update lwip to STABLE-2_1_2_RELEASE for net_lwip_webserver
+ - Update lwip to STABLE-2_1_2_RELEASE for ``net_lwip_webserver``
-- Added new Audio example: audio_test uac2_headsest
+- Added new Audio example: ``audio_test`` ``uac2_headsest``
New Boards
----------
@@ -1110,37 +1110,37 @@ Added
- Added multiple instances support for CDC and MIDI
- Added a handful of unit test with Ceedling.
- Added LOG support for debugging with CFG_TUSB_DEBUG
-- Added `tud_descriptor_bos_cb()` for BOS descriptor (required for USB 2.1)
-- Added `dcd_edpt0_status_complete()` as optional API for DCD
+- Added ``tud_descriptor_bos_cb()`` for BOS descriptor (required for USB 2.1)
+- Added ``dcd_edpt0_status_complete()`` as optional API for DCD
**Examples**
Following examples are added:
-- board_test
-- cdc_dual_ports
-- dfu_rt
-- hid_composite
-- net_lwip_webserver
-- usbtmc
-- webusb_serial
+- ``board_test``
+- ``cdc_dual_ports``
+- ``dfu_rt``
+- ``hid_composite``
+- ``net_lwip_webserver``
+- ``usbtmc``
+- ``webusb_serial``
Changed
-------
-- Changed `tud_descriptor_string_cb()` to have additional Language ID argument
-- Merged hal_nrf5x.c into dcd_nrf5x.c
-- Merged dcd_samd21.c and dcd_samd51.c into dcd_samd.c
-- Generalized dcd_stm32f4.c to dcd_synopsys.c
-- Changed cdc_msc_hid to cdc_msc (drop hid) due to limited endpoints number of some MCUs
+- Changed ``tud_descriptor_string_cb()`` to have additional Language ID argument
+- Merged ``hal_nrf5x.c`` into ``dcd_nrf5x.c``
+- Merged ``dcd_samd21.c`` and ``dcd_samd51.c`` into ``dcd_samd.c``
+- Generalized ``dcd_stm32f4.c`` to ``dcd_synopsys.c``
+- Changed ``cdc_msc_hid`` to ``cdc_msc`` (drop hid) due to limited endpoints number of some MCUs
- Improved DCD SAMD stability, fix missing setup packet occasionally
-- Improved usbd/usbd_control with proper handling of zero-length packet (ZLP)
+- Improved ``usbd/usbd_control`` with proper handling of zero-length packet (ZLP)
- Improved STM32 DCD FSDev
- Improved STM32 DCD Synopsys
- Migrated CI from Travis to Github Action
- Updated nrfx submodule to 2.1.0
- Fixed mynewt osal queue definition
-- Fixed cdc_msc_freertos example build for all MCUs
+- Fixed ``cdc_msc_freertos`` example build for all MCUs
0.5.0 (2019-06)
diff --git a/docs/info/contributors.rst b/docs/info/contributors.rst
deleted file mode 120000
index 35e0b05f5..000000000
--- a/docs/info/contributors.rst
+++ /dev/null
@@ -1 +0,0 @@
-.. include:: ../../CONTRIBUTORS.rst
\ No newline at end of file
diff --git a/docs/info/contributors.rst b/docs/info/contributors.rst
new file mode 100644
index 000000000..35e0b05f5
--- /dev/null
+++ b/docs/info/contributors.rst
@@ -0,0 +1 @@
+.. include:: ../../CONTRIBUTORS.rst
\ No newline at end of file
diff --git a/docs/reference/getting_started.rst b/docs/reference/getting_started.rst
index 963420f7b..37745d6a1 100644
--- a/docs/reference/getting_started.rst
+++ b/docs/reference/getting_started.rst
@@ -7,17 +7,17 @@ Add TinyUSB to your project
It is relatively simple to incorporate tinyusb to your project
-* Copy or ``git submodule`` this repo into your project in a subfolder. Let's say it is *your_project/tinyusb*
-* Add all the .c in the ``tinyusb/src`` folder to your project
-* Add *your_project/tinyusb/src* to your include path. Also make sure your current include path also contains the configuration file tusb_config.h.
-* Make sure all required macros are all defined properly in tusb_config.h (configure file in demo application is sufficient, but you need to add a few more such as ``CFG_TUSB_MCU``, ``CFG_TUSB_OS`` since they are passed by IDE/compiler to maintain a unique configure for all boards).
+* Copy or ``git submodule`` this repo into your project in a subfolder. Let's say it is ``your_project/tinyusb``
+* Add all the ``.c`` in the ``tinyusb/src`` folder to your project
+* Add ``your_project/tinyusb/src`` to your include path. Also make sure your current include path also contains the configuration file ``tusb_config.h``.
+* Make sure all required macros are all defined properly in ``tusb_config.h`` (configure file in demo application is sufficient, but you need to add a few more such as ``CFG_TUSB_MCU``, ``CFG_TUSB_OS`` since they are passed by IDE/compiler to maintain a unique configure for all boards).
* If you use the device stack, make sure you have created/modified usb descriptors for your own need. Ultimately you need to implement all **tud descriptor** callbacks for the stack to work.
-* Add tusb_init(rhport, role) call to your reset initialization code.
+* Add ``tusb_init(rhport, role)`` call to your reset initialization code.
* Call ``tusb_int_handler(rhport, in_isr)`` in your USB IRQ Handler
* Implement all enabled classes's callbacks.
-* If you don't use any RTOSes at all, you need to continuously and/or periodically call tud_task()/tuh_task() function. All of the callbacks and functionality are handled and invoked within the call of that task runner.
+* If you don't use any RTOSes at all, you need to continuously and/or periodically call ``tud_task()``/``tuh_task()`` function. All of the callbacks and functionality are handled and invoked within the call of that task runner.
-.. code-block::
+.. code-block:: c
int main(void) {
tusb_rhport_init_t dev_init = {
@@ -50,9 +50,9 @@ It is relatively simple to incorporate tinyusb to your project
Examples
--------
-For your convenience, TinyUSB contains a handful of examples for both host and device with/without RTOS to quickly test the functionality as well as demonstrate how API() should be used. Most examples will work on most of `the supported boards `_. Firstly we need to ``git clone`` if not already
+For your convenience, TinyUSB contains a handful of examples for both host and device with/without RTOS to quickly test the functionality as well as demonstrate how API should be used. Most examples will work on most of `the supported boards `_. Firstly we need to ``git clone`` if not already
-.. code-block::
+.. code-block:: bash
$ git clone https://github.com/hathach/tinyusb tinyusb
$ cd tinyusb
@@ -62,17 +62,17 @@ Some ports will also require a port-specific SDK (e.g. RP2040) or binary (e.g. S
Dependencies
^^^^^^^^^^^^
-The hardware code is located in ``hw/bsp`` folder, and is organized by family/boards. e.g raspberry_pi_pico is located in ``hw/bsp/rp2040/boards/raspberry_pi_pico`` where FAMILY=rp2040 and BOARD=raspberry_pi_pico. Before building, we firstly need to download dependencies such as: MCU low-level peripheral driver and external libraries e.g FreeRTOS (required by some examples). We can do that by either ways:
+The hardware code is located in ``hw/bsp`` folder, and is organized by family/boards. e.g raspberry_pi_pico is located in ``hw/bsp/rp2040/boards/raspberry_pi_pico`` where ``FAMILY=rp2040`` and ``BOARD=raspberry_pi_pico``. Before building, we firstly need to download dependencies such as: MCU low-level peripheral driver and external libraries e.g FreeRTOS (required by some examples). We can do that by either ways:
1. Run ``tools/get_deps.py {FAMILY}`` script to download all dependencies for a family as follow. Note: For TinyUSB developer to download all dependencies, use FAMILY=all.
-.. code-block::
+.. code-block:: bash
$ python tools/get_deps.py rp2040
2. Or run the ``get-deps`` target in one of the example folder as follow.
-.. code-block::
+.. code-block:: bash
$ cd examples/device/cdc_msc
$ make BOARD=raspberry_pi_pico get-deps
@@ -84,19 +84,19 @@ Build
To build example, first change directory to an example folder.
-.. code-block::
+.. code-block:: bash
$ cd examples/device/cdc_msc
Then compile with ``make BOARD={board_name} all`` , for example
-.. code-block::
+.. code-block:: bash
$ make BOARD=raspberry_pi_pico all
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 ``99-tinyusb.rules`` and reload your udev is good to go
-.. code-block::
+.. code-block:: bash
$ cp examples/device/99-tinyusb.rules /etc/udev/rules.d/
$ sudo udevadm control --reload-rules && sudo udevadm trigger
@@ -106,7 +106,7 @@ RootHub Port Selection
If a board has several ports, one port is chosen by default in the individual board.mk file. Use option ``PORT=x`` To choose another port. For example to select the HS port of a STM32F746Disco board, use:
-.. code-block::
+.. code-block:: bash
$ make BOARD=stm32f746disco PORT=1 all
@@ -115,16 +115,16 @@ Port Speed
A MCU can support multiple operational speed. By default, the example build system will use the fastest supported on the board. Use option ``SPEED=full/high`` e.g To force F723 operate at full instead of default high speed
-.. code-block::
+.. code-block:: bash
$ make BOARD=stm32f746disco SPEED=full all
Size Analysis
~~~~~~~~~~~~~
-First install `linkermap tool `_ then ``linkermap`` target can be used to analyze code size. You may want to compile with ``NO_LTO=1`` since -flto merges code across .o files and make it difficult to analyze.
+First install `linkermap tool `_ then ``linkermap`` target can be used to analyze code size. You may want to compile with ``NO_LTO=1`` since ``-flto`` merges code across ``.o`` files and make it difficult to analyze.
-.. code-block::
+.. code-block:: bash
$ make BOARD=feather_nrf52840_express NO_LTO=1 all linkermap
@@ -133,16 +133,16 @@ Debug
To compile for debugging add ``DEBUG=1``\ , for example
-.. code-block::
+.. code-block:: bash
$ make BOARD=feather_nrf52840_express DEBUG=1 all
Log
~~~
-Should you have an issue running example and/or submitting an bug report. You could enable TinyUSB built-in debug logging with optional ``LOG=``. LOG=1 will only print out error message, LOG=2 print more information with on-going events. LOG=3 or higher is not used yet.
+Should you have an issue running example and/or submitting an bug report. You could enable TinyUSB built-in debug logging with optional ``LOG=``. ``LOG=1`` will only print out error message, ``LOG=2`` print more information with on-going events. ``LOG=3`` or higher is not used yet.
-.. code-block::
+.. code-block:: bash
$ make BOARD=feather_nrf52840_express LOG=2 all
@@ -164,7 +164,7 @@ By default log message is printed via on-board UART which is slow and take lots
* Pros: should be compatible with more debugger that support SWO.
* Software viewer should be provided along with your debugger driver.
-.. code-block::
+.. code-block:: bash
$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=rtt all
$ make BOARD=feather_nrf52840_express LOG=2 LOGGER=swo all
@@ -174,20 +174,20 @@ Flash
``flash`` target will use the default on-board debugger (jlink/cmsisdap/stlink/dfu) to flash the binary, please install those support software in advance. Some board use bootloader/DFU via serial which is required to pass to make command
-.. code-block::
+.. code-block:: bash
$ make BOARD=feather_nrf52840_express flash
$ make SERIAL=/dev/ttyACM0 BOARD=feather_nrf52840_express flash
Since jlink can be used with most of the boards, there is also ``flash-jlink`` target for your convenience.
-.. code-block::
+.. code-block:: bash
$ make BOARD=feather_nrf52840_express flash-jlink
Some board use uf2 bootloader for drag & drop in to mass storage device, uf2 can be generated with ``uf2`` target
-.. code-block::
+.. code-block:: bash
$ make BOARD=feather_nrf52840_express all uf2
@@ -199,23 +199,23 @@ Use project connection
IAR Project Connection files are provided to import TinyUSB stack into your project.
-* A buldable project of your MCU need to be created in advance.
+* A buildable project of your MCU need to be created in advance.
* Take example of STM32F0:
- - You need `stm32l0xx.h`, `startup_stm32f0xx.s`, `system_stm32f0xx.c`.
+ - You need ``stm32l0xx.h``, ``startup_stm32f0xx.s``, ``system_stm32f0xx.c``.
- - `STM32L0xx_HAL_Driver` is only needed to run examples, TinyUSB stack itself doesn't rely on MCU's SDKs.
+ - ``STM32L0xx_HAL_Driver`` is only needed to run examples, TinyUSB stack itself doesn't rely on MCU's SDKs.
-* Open ``Tools -> Configure Custom Argument Variables`` (Switch to `Global` tab if you want to do it for all your projects)
- Click `New Group ...`, name it to `TUSB`, Click `Add Variable ...`, name it to `TUSB_DIR`, change it's value to the path of your TinyUSB stack,
- for example `C:\\tinyusb`
+* Open ``Tools -> Configure Custom Argument Variables`` (Switch to ``Global`` tab if you want to do it for all your projects)
+ Click ``New Group ...``, name it to ``TUSB``, Click ``Add Variable ...``, name it to ``TUSB_DIR``, change it's value to the path of your TinyUSB stack,
+ for example ``C:\\tinyusb``
Import stack only
~~~~~~~~~~~~~~~~~
-1. Open ``Project -> Add project Connection ...``, click `OK`, choose `tinyusb\\tools\\iar_template.ipcf`.
+1. Open ``Project -> Add project Connection ...``, click ``OK``, choose ``tinyusb\\tools\\iar_template.ipcf``.
Run examples
~~~~~~~~~~~~
@@ -224,11 +224,11 @@ Run examples
.. code-block::
- cd C:\tinyusb\tools
- python iar_gen.py
+ > cd C:\tinyusb\tools
+ > python iar_gen.py
-2. Open `Project -> Add project Connection ...`, click `OK`, choose `tinyusb\\examples\\(.ipcf of example)`.
- For example `C:\\tinyusb\\examples\\device\\cdc_msc\\iar_cdc_msc.ipcf`
+2. Open ``Project -> Add project Connection ...``, click ``OK``, choose ``tinyusb\\examples\\(.ipcf of example)``.
+ For example ``C:\\tinyusb\\examples\\device\\cdc_msc\\iar_cdc_msc.ipcf``
Native CMake support (9.50.1+)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -239,5 +239,5 @@ Following these steps:
1. Add IAR compiler binary path to system ``PATH`` environment variable, such as ``C:\Program Files\IAR Systems\Embedded Workbench 9.2\arm\bin``.
2. Create new project in IAR, in Tool chain dropdown menu, choose CMake for Arm then Import ``CMakeLists.txt`` from chosen example directory.
-3. Set up board option in ``Option - CMake/CMSIS-TOOLBOX - CMake``, for example :code:`-DBOARD=stm32f439nucleo -DTOOLCHAIN=iar`, **Uncheck 'Override tools in env'**.
+3. Set up board option in ``Option - CMake/CMSIS-TOOLBOX - CMake``, for example ``-DBOARD=stm32f439nucleo -DTOOLCHAIN=iar``, **Uncheck 'Override tools in env'**.
4. (For debug only) Choose correct CPU model in ``Option - General Options - Target``, to profit register and memory view.
diff --git a/examples/CMakePresets.json b/examples/CMakePresets.json
new file mode 100644
index 000000000..2f904a269
--- /dev/null
+++ b/examples/CMakePresets.json
@@ -0,0 +1,6 @@
+{
+ "version": 6,
+ "include": [
+ "../hw/bsp/BoardPresets.json"
+ ]
+}
diff --git a/examples/build_system/make/make.mk b/examples/build_system/make/make.mk
index 1500a51e0..3101b66b9 100644
--- a/examples/build_system/make/make.mk
+++ b/examples/build_system/make/make.mk
@@ -6,7 +6,6 @@
# Toolchain
# Can be changed via TOOLCHAIN=gcc|iar or CC=arm-none-eabi-gcc|iccarm|clang
#-------------------------------------------------------------
-
ifneq (,$(findstring clang,$(CC)))
TOOLCHAIN = clang
else ifneq (,$(findstring iccarm,$(CC)))
@@ -65,7 +64,9 @@ BUILD := _build/$(BOARD)
PROJECT := $(notdir $(CURDIR))
BIN := $(TOP)/_bin/$(BOARD)/$(notdir $(CURDIR))
-#-------------- Select the board to build for. ------------
+#-------------------------------------------------------------
+# Board / Family
+#-------------------------------------------------------------
# Board without family
ifneq ($(wildcard $(TOP)/hw/bsp/$(BOARD)/board.mk),)
@@ -93,7 +94,9 @@ else
SRC_C += $(subst $(TOP)/,,$(wildcard $(TOP)/$(FAMILY_PATH)/*.c))
endif
-#-------------- Source files and compiler flags --------------
+#-------------------------------------------------------------
+# Source files and compiler flags
+#-------------------------------------------------------------
# tinyusb makefile
include $(TOP)/src/tinyusb.mk
SRC_C += $(TINYUSB_SRC_C)
@@ -148,7 +151,37 @@ endif
# toolchain specific
include ${TOP}/examples/build_system/make/toolchain/arm_$(TOOLCHAIN).mk
-# Handy check parameter function
+#---------------------- FreeRTOS -----------------------
+FREERTOS_SRC = lib/FreeRTOS-Kernel
+FREERTOS_PORTABLE_PATH = $(FREERTOS_SRC)/portable/$(if $(findstring iar,$(TOOLCHAIN)),IAR,GCC)
+
+ifeq ($(RTOS),freertos)
+ SRC_C += \
+ $(FREERTOS_SRC)/list.c \
+ $(FREERTOS_SRC)/queue.c \
+ $(FREERTOS_SRC)/tasks.c \
+ $(FREERTOS_SRC)/timers.c \
+ $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.c))
+
+ SRC_S += $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.s))
+ INC += \
+ $(TOP)/hw/bsp/$(FAMILY)/FreeRTOSConfig \
+ $(TOP)/$(FREERTOS_SRC)/include \
+ $(TOP)/$(FREERTOS_PORTABLE_SRC)
+
+ CFLAGS += -DCFG_TUSB_OS=OPT_OS_FREERTOS
+
+ # Suppress FreeRTOSConfig.h warnings
+ CFLAGS_GCC += -Wno-error=redundant-decls
+
+ # Suppress FreeRTOS source warnings
+ CFLAGS_GCC += -Wno-error=cast-qual
+
+ # FreeRTOS (lto + Os) linker issue
+ LDFLAGS_GCC += -Wl,--undefined=vTaskSwitchContext
+endif
+
+#---------------- Helper ----------------
check_defined = \
$(strip $(foreach 1,$1, \
$(call __check_defined,$1,$(strip $(value 2)))))
diff --git a/examples/device/CMakePresets.json b/examples/device/CMakePresets.json
new file mode 100644
index 000000000..c22e8c0ec
--- /dev/null
+++ b/examples/device/CMakePresets.json
@@ -0,0 +1,6 @@
+{
+ "version": 6,
+ "include": [
+ "../../hw/bsp/BoardPresets.json"
+ ]
+}
diff --git a/examples/device/audio_4_channel_mic/CMakePresets.json b/examples/device/audio_4_channel_mic/CMakePresets.json
new file mode 100644
index 000000000..5cd8971e9
--- /dev/null
+++ b/examples/device/audio_4_channel_mic/CMakePresets.json
@@ -0,0 +1,6 @@
+{
+ "version": 6,
+ "include": [
+ "../../../hw/bsp/BoardPresets.json"
+ ]
+}
diff --git a/examples/device/audio_4_channel_mic_freertos/CMakePresets.json b/examples/device/audio_4_channel_mic_freertos/CMakePresets.json
new file mode 100644
index 000000000..5cd8971e9
--- /dev/null
+++ b/examples/device/audio_4_channel_mic_freertos/CMakePresets.json
@@ -0,0 +1,6 @@
+{
+ "version": 6,
+ "include": [
+ "../../../hw/bsp/BoardPresets.json"
+ ]
+}
diff --git a/examples/device/audio_4_channel_mic_freertos/Makefile b/examples/device/audio_4_channel_mic_freertos/Makefile
index 0202f631c..bd625b345 100644
--- a/examples/device/audio_4_channel_mic_freertos/Makefile
+++ b/examples/device/audio_4_channel_mic_freertos/Makefile
@@ -1,14 +1,9 @@
+RTOS = freertos
include ../../build_system/make/make.mk
-FREERTOS_SRC = lib/FreeRTOS-Kernel
-FREERTOS_PORTABLE_PATH = $(FREERTOS_SRC)/portable/$(if $(findstring iar,$(TOOLCHAIN)),IAR,GCC)
-
INC += \
src \
- src/FreeRTOSConfig \
$(TOP)/hw \
- $(TOP)/$(FREERTOS_SRC)/include \
- $(TOP)/$(FREERTOS_PORTABLE_SRC) \
# Example source
EXAMPLE_SOURCE = \
@@ -17,21 +12,4 @@ EXAMPLE_SOURCE = \
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
-# FreeRTOS source, all files in port folder
-SRC_C += \
- $(FREERTOS_SRC)/list.c \
- $(FREERTOS_SRC)/queue.c \
- $(FREERTOS_SRC)/tasks.c \
- $(FREERTOS_SRC)/timers.c \
- $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.c))
-
-SRC_S += \
- $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.s))
-
-# Suppress FreeRTOS warnings
-CFLAGS += -Wno-error=cast-qual -Wno-error=redundant-decls
-
-# FreeRTOS (lto + Os) linker issue
-LDFLAGS += -Wl,--undefined=vTaskSwitchContext
-
include ../../build_system/make/rules.mk
diff --git a/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
deleted file mode 100644
index 902a54f08..000000000
--- a/examples/device/audio_4_channel_mic_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * FreeRTOS Kernel V10.0.0
- * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * 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. If you wish to use our Amazon
- * FreeRTOS name, please do so in a fair use way that does not cause confusion.
- *
- * 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.
- *
- * http://www.FreeRTOS.org
- * http://aws.amazon.com/freertos
- *
- * 1 tab == 4 spaces!
- */
-
-
-#ifndef FREERTOS_CONFIG_H
-#define FREERTOS_CONFIG_H
-
-/*-----------------------------------------------------------
- * Application specific definitions.
- *
- * These definitions should be adjusted for your particular hardware and
- * application requirements.
- *
- * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
- * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
- *
- * See http://www.freertos.org/a00110.html.
- *----------------------------------------------------------*/
-
-// skip if included from IAR assembler
-#ifndef __IASMARM__
-
-// Include MCU header
-#include "bsp/board_mcu.h"
-
-#if TUSB_MCU_VENDOR_ESPRESSIF
- #error "ESP32-Sx should use IDF's FreeRTOSConfig.h"
-#endif
-
-// TODO fix later
-#if CFG_TUSB_MCU == OPT_MCU_MM32F327X
- extern u32 SystemCoreClock;
-#else
- // FIXME cause redundant-decls warnings
- extern uint32_t SystemCoreClock;
-#endif
-
-#endif
-
-/* Cortex M23/M33 port configuration. */
-#define configENABLE_MPU 0
-#define configENABLE_FPU 1
-#define configENABLE_TRUSTZONE 0
-#define configMINIMAL_SECURE_STACK_SIZE ( 1024 )
-#define configRUN_FREERTOS_SECURE_ONLY 1
-
-#define configUSE_PREEMPTION 1
-#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
-#define configCPU_CLOCK_HZ SystemCoreClock
-#define configTICK_RATE_HZ ( 1000 )
-#define configMAX_PRIORITIES ( 5 )
-#define configMINIMAL_STACK_SIZE ( 128 )
-#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 )
-#define configMAX_TASK_NAME_LEN 16
-#define configUSE_16_BIT_TICKS 0
-#define configIDLE_SHOULD_YIELD 1
-#define configUSE_MUTEXES 1
-#define configUSE_RECURSIVE_MUTEXES 1
-#define configUSE_COUNTING_SEMAPHORES 1
-#define configQUEUE_REGISTRY_SIZE 4
-#define configUSE_QUEUE_SETS 0
-#define configUSE_TIME_SLICING 0
-#define configUSE_NEWLIB_REENTRANT 0
-#define configENABLE_BACKWARD_COMPATIBILITY 1
-#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
-
-#define configSUPPORT_STATIC_ALLOCATION 1
-#define configSUPPORT_DYNAMIC_ALLOCATION 0
-
-/* Hook function related definitions. */
-#define configUSE_IDLE_HOOK 0
-#define configUSE_TICK_HOOK 0
-#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning
-#define configCHECK_FOR_STACK_OVERFLOW 2
-#define configCHECK_HANDLER_INSTALLATION 0
-
-/* Run time and task stats gathering related definitions. */
-#define configGENERATE_RUN_TIME_STATS 0
-#define configUSE_TRACE_FACILITY 1 // legacy trace
-#define configUSE_STATS_FORMATTING_FUNCTIONS 0
-
-/* Co-routine definitions. */
-#define configUSE_CO_ROUTINES 0
-#define configMAX_CO_ROUTINE_PRIORITIES 2
-
-/* Software timer related definitions. */
-#define configUSE_TIMERS 1
-#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2)
-#define configTIMER_QUEUE_LENGTH 32
-#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
-
-/* Optional functions - most linkers will remove unused functions anyway. */
-#define INCLUDE_vTaskPrioritySet 0
-#define INCLUDE_uxTaskPriorityGet 0
-#define INCLUDE_vTaskDelete 0
-#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY
-#define INCLUDE_xResumeFromISR 0
-#define INCLUDE_vTaskDelayUntil 1
-#define INCLUDE_vTaskDelay 1
-#define INCLUDE_xTaskGetSchedulerState 0
-#define INCLUDE_xTaskGetCurrentTaskHandle 0
-#define INCLUDE_uxTaskGetStackHighWaterMark 0
-#define INCLUDE_xTaskGetIdleTaskHandle 0
-#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
-#define INCLUDE_pcTaskGetTaskName 0
-#define INCLUDE_eTaskGetState 0
-#define INCLUDE_xEventGroupSetBitFromISR 0
-#define INCLUDE_xTimerPendFunctionCall 0
-
-#ifdef __RX__
-/* Renesas RX series */
-#define vSoftwareInterruptISR INT_Excep_ICU_SWINT
-#define vTickISR INT_Excep_CMT0_CMI0
-#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2)
-#define configKERNEL_INTERRUPT_PRIORITY 1
-#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4
-
-#else
-
-/* FreeRTOS hooks to NVIC vectors */
-#define xPortPendSVHandler PendSV_Handler
-#define xPortSysTickHandler SysTick_Handler
-#define vPortSVCHandler SVC_Handler
-
-//--------------------------------------------------------------------+
-// Interrupt nesting behavior configuration.
-//--------------------------------------------------------------------+
-#if defined(__NVIC_PRIO_BITS)
- // For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h
- #define configPRIO_BITS __NVIC_PRIO_BITS
-
-#elif defined(__ECLIC_INTCTLBITS)
- // RISC-V Bumblebee core from nuclei
- #define configPRIO_BITS __ECLIC_INTCTLBITS
-
-#elif defined(__IASMARM__)
- // FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS.
- // Therefore we will hard coded it to minimum value of 2 to get pass ci build.
- // IAR user must update this to correct value of the target MCU
- #message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU"
- #define configPRIO_BITS 2
-
-#else
- #error "FreeRTOS configPRIO_BITS to be defined"
-#endif
-
-/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
-#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1< missing data with hardware test loop
+ board_delay(20);
return;
}
- // Get String descriptor using Sync API
- uint16_t serial[64];
- uint16_t buf[128];
-
- cdc_printf("Device %u: ID %04x:%04x SN ", daddr, desc_device.idVendor, desc_device.idProduct);
- xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, serial, sizeof(serial));
- if (XFER_RESULT_SUCCESS != xfer_result) {
- serial[0] = 'n';
- serial[1] = '/';
- serial[2] = 'a';
- serial[3] = 0;
- }
- print_utf16(serial, TU_ARRAY_SIZE(serial));
- tud_cdc_write_str("\r\n");
-
- cdc_printf("Device Descriptor:\r\n");
- cdc_printf(" bLength %u\r\n" , desc_device.bLength);
- cdc_printf(" bDescriptorType %u\r\n" , desc_device.bDescriptorType);
- cdc_printf(" bcdUSB %04x\r\n" , desc_device.bcdUSB);
- cdc_printf(" bDeviceClass %u\r\n" , desc_device.bDeviceClass);
- cdc_printf(" bDeviceSubClass %u\r\n" , desc_device.bDeviceSubClass);
- cdc_printf(" bDeviceProtocol %u\r\n" , desc_device.bDeviceProtocol);
- cdc_printf(" bMaxPacketSize0 %u\r\n" , desc_device.bMaxPacketSize0);
- cdc_printf(" idVendor 0x%04x\r\n" , desc_device.idVendor);
- cdc_printf(" idProduct 0x%04x\r\n" , desc_device.idProduct);
- cdc_printf(" bcdDevice %04x\r\n" , desc_device.bcdDevice);
-
- cdc_printf(" iManufacturer %u " , desc_device.iManufacturer);
- xfer_result = tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, buf, sizeof(buf));
- if (XFER_RESULT_SUCCESS == xfer_result ) {
- print_utf16(buf, TU_ARRAY_SIZE(buf));
- }
- tud_cdc_write_str("\r\n");
-
- cdc_printf(" iProduct %u " , desc_device.iProduct);
- xfer_result = tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, buf, sizeof(buf));
- if (XFER_RESULT_SUCCESS == xfer_result) {
- print_utf16(buf, TU_ARRAY_SIZE(buf));
- }
- tud_cdc_write_str("\r\n");
-
- cdc_printf(" iSerialNumber %u " , desc_device.iSerialNumber);
- tud_cdc_write_str((char*)serial); // serial is already to UTF-8
- tud_cdc_write_str("\r\n");
-
- cdc_printf(" bNumConfigurations %u\r\n" , desc_device.bNumConfigurations);
-}
-
-void cdc_task(void) {
- if (tud_cdc_connected()) {
- for (uint8_t daddr = 1; daddr <= CFG_TUH_DEVICE_MAX; daddr++) {
- if (tuh_mounted(daddr)) {
- if (is_print[daddr]) {
- is_print[daddr] = false;
- print_device_info(daddr);
- tud_cdc_write_flush();
- }
+ for (uint8_t daddr = 1; daddr <= CFG_TUH_DEVICE_MAX; daddr++) {
+ if (tuh_mounted(daddr)) {
+ if (is_print[daddr]) {
+ is_print[daddr] = false;
+ print_device_info(daddr, &descriptor_device[daddr]);
+ tud_cdc_write_flush();
}
}
}
@@ -221,6 +160,77 @@ void cdc_task(void) {
//--------------------------------------------------------------------+
// Host Get device information
//--------------------------------------------------------------------+
+#define cdc_printf(...) \
+ do { \
+ char _tempbuf[256]; \
+ char* _bufptr = _tempbuf; \
+ uint32_t count = (uint32_t) sprintf(_tempbuf, __VA_ARGS__); \
+ while (count > 0) { \
+ uint32_t wr_count = tud_cdc_write(_bufptr, count); \
+ count -= wr_count; \
+ _bufptr += wr_count; \
+ if (count > 0){ \
+ tud_task();\
+ tud_cdc_write_flush(); \
+ } \
+ } \
+ } while(0)
+
+static void print_device_info(uint8_t daddr, const tusb_desc_device_t* desc_device) {
+ // Get String descriptor using Sync API
+ uint16_t serial[64];
+ uint16_t buf[128];
+ (void) buf;
+
+ cdc_printf("Device %u: ID %04x:%04x SN ", daddr, desc_device->idVendor, desc_device->idProduct);
+ uint8_t xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, serial, sizeof(serial));
+ if (XFER_RESULT_SUCCESS != xfer_result) {
+ serial[0] = 'n';
+ serial[1] = '/';
+ serial[2] = 'a';
+ serial[3] = 0;
+ }
+ print_utf16(serial, TU_ARRAY_SIZE(serial));
+ cdc_printf("\r\n");
+
+ cdc_printf("Device Descriptor:\r\n");
+ cdc_printf(" bLength %u\r\n" , desc_device->bLength);
+ cdc_printf(" bDescriptorType %u\r\n" , desc_device->bDescriptorType);
+ cdc_printf(" bcdUSB %04x\r\n" , desc_device->bcdUSB);
+ cdc_printf(" bDeviceClass %u\r\n" , desc_device->bDeviceClass);
+ cdc_printf(" bDeviceSubClass %u\r\n" , desc_device->bDeviceSubClass);
+ cdc_printf(" bDeviceProtocol %u\r\n" , desc_device->bDeviceProtocol);
+ cdc_printf(" bMaxPacketSize0 %u\r\n" , desc_device->bMaxPacketSize0);
+ cdc_printf(" idVendor 0x%04x\r\n" , desc_device->idVendor);
+ cdc_printf(" idProduct 0x%04x\r\n" , desc_device->idProduct);
+ cdc_printf(" bcdDevice %04x\r\n" , desc_device->bcdDevice);
+
+ cdc_printf(" iManufacturer %u " , desc_device->iManufacturer);
+ xfer_result = tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, buf, sizeof(buf));
+ if (XFER_RESULT_SUCCESS == xfer_result) {
+ print_utf16(buf, TU_ARRAY_SIZE(buf));
+ }
+ cdc_printf("\r\n");
+
+ cdc_printf(" iProduct %u " , desc_device->iProduct);
+ xfer_result = tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, buf, sizeof(buf));
+ if (XFER_RESULT_SUCCESS == xfer_result) {
+ print_utf16(buf, TU_ARRAY_SIZE(buf));
+ }
+ cdc_printf("\r\n");
+
+ cdc_printf(" iSerialNumber %u " , desc_device->iSerialNumber);
+ cdc_printf((char*)serial); // serial is already to UTF-8
+ cdc_printf("\r\n");
+
+ cdc_printf(" bNumConfigurations %u\r\n" , desc_device->bNumConfigurations);
+}
+
+void tuh_enum_descriptor_device_cb(uint8_t daddr, tusb_desc_device_t const* desc_device) {
+ (void) daddr;
+ descriptor_device[daddr] = *desc_device; // save device descriptor
+}
+
void tuh_mount_cb(uint8_t daddr) {
printf("mounted device %u\r\n", daddr);
is_print[daddr] = true;
@@ -296,7 +306,5 @@ static void print_utf16(uint16_t *temp_buf, size_t buf_len) {
_convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len);
((uint8_t*) temp_buf)[utf8_len] = '\0';
- tud_cdc_write(temp_buf, utf8_len);
- tud_cdc_write_flush();
- tud_task();
+ cdc_printf((char*) temp_buf);
}
diff --git a/examples/host/CMakeLists.txt b/examples/host/CMakeLists.txt
index 175646830..2783dd84e 100644
--- a/examples/host/CMakeLists.txt
+++ b/examples/host/CMakeLists.txt
@@ -11,4 +11,5 @@ family_add_subdirectory(cdc_msc_hid)
family_add_subdirectory(cdc_msc_hid_freertos)
family_add_subdirectory(device_info)
family_add_subdirectory(hid_controller)
+family_add_subdirectory(midi_rx)
family_add_subdirectory(msc_file_explorer)
diff --git a/examples/host/CMakePresets.json b/examples/host/CMakePresets.json
new file mode 100644
index 000000000..c22e8c0ec
--- /dev/null
+++ b/examples/host/CMakePresets.json
@@ -0,0 +1,6 @@
+{
+ "version": 6,
+ "include": [
+ "../../hw/bsp/BoardPresets.json"
+ ]
+}
diff --git a/examples/host/bare_api/CMakePresets.json b/examples/host/bare_api/CMakePresets.json
new file mode 100644
index 000000000..5cd8971e9
--- /dev/null
+++ b/examples/host/bare_api/CMakePresets.json
@@ -0,0 +1,6 @@
+{
+ "version": 6,
+ "include": [
+ "../../../hw/bsp/BoardPresets.json"
+ ]
+}
diff --git a/examples/host/bare_api/src/main.c b/examples/host/bare_api/src/main.c
index f582f4f5a..0c76ff0c9 100644
--- a/examples/host/bare_api/src/main.c
+++ b/examples/host/bare_api/src/main.c
@@ -55,16 +55,15 @@ uint8_t* get_hid_buf(uint8_t daddr);
void free_hid_buf(uint8_t daddr);
/*------------- MAIN -------------*/
-int main(void)
-{
+int main(void) {
board_init();
printf("TinyUSB Bare API Example\r\n");
// init host stack on configured roothub port
tusb_rhport_init_t host_init = {
- .role = TUSB_ROLE_HOST,
- .speed = TUSB_SPEED_AUTO
+ .role = TUSB_ROLE_HOST,
+ .speed = TUSB_SPEED_AUTO
};
tusb_init(BOARD_TUH_RHPORT, &host_init);
@@ -72,8 +71,7 @@ int main(void)
board_init_after_tusb();
}
- while (1)
- {
+ while (1) {
// tinyusb host task
tuh_task();
led_blinking_task();
@@ -85,8 +83,7 @@ int main(void)
/*------------- TinyUSB Callbacks -------------*/
// Invoked when device is mounted (configured)
-void tuh_mount_cb (uint8_t daddr)
-{
+void tuh_mount_cb(uint8_t daddr) {
printf("Device attached, address = %d\r\n", daddr);
// Get Device Descriptor
@@ -95,8 +92,7 @@ void tuh_mount_cb (uint8_t daddr)
}
/// Invoked when device is unmounted (bus reset/unplugged)
-void tuh_umount_cb(uint8_t daddr)
-{
+void tuh_umount_cb(uint8_t daddr) {
printf("Device removed, address = %d\r\n", daddr);
free_hid_buf(daddr);
}
@@ -104,11 +100,8 @@ void tuh_umount_cb(uint8_t daddr)
//--------------------------------------------------------------------+
// Device Descriptor
//--------------------------------------------------------------------+
-
-void print_device_descriptor(tuh_xfer_t* xfer)
-{
- if ( XFER_RESULT_SUCCESS != xfer->result )
- {
+void print_device_descriptor(tuh_xfer_t *xfer) {
+ if (XFER_RESULT_SUCCESS != xfer->result) {
printf("Failed to get device descriptor\r\n");
return;
}
@@ -131,33 +124,29 @@ void print_device_descriptor(tuh_xfer_t* xfer)
// Get String descriptor using Sync API
uint16_t temp_buf[128];
- printf(" iManufacturer %u " , desc_device.iManufacturer);
- if (XFER_RESULT_SUCCESS == tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf)) )
- {
+ printf(" iManufacturer %u ", desc_device.iManufacturer);
+ if (XFER_RESULT_SUCCESS == tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf))) {
print_utf16(temp_buf, TU_ARRAY_SIZE(temp_buf));
}
printf("\r\n");
- printf(" iProduct %u " , desc_device.iProduct);
- if (XFER_RESULT_SUCCESS == tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf)))
- {
+ printf(" iProduct %u ", desc_device.iProduct);
+ if (XFER_RESULT_SUCCESS == tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf))) {
print_utf16(temp_buf, TU_ARRAY_SIZE(temp_buf));
}
printf("\r\n");
- printf(" iSerialNumber %u " , desc_device.iSerialNumber);
- if (XFER_RESULT_SUCCESS == tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf)))
- {
+ printf(" iSerialNumber %u ", desc_device.iSerialNumber);
+ if (XFER_RESULT_SUCCESS == tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, temp_buf, sizeof(temp_buf))) {
print_utf16(temp_buf, TU_ARRAY_SIZE(temp_buf));
}
printf("\r\n");
- printf(" bNumConfigurations %u\r\n" , desc_device.bNumConfigurations);
+ printf(" bNumConfigurations %u\r\n", desc_device.bNumConfigurations);
// Get configuration descriptor with sync API
- if (XFER_RESULT_SUCCESS == tuh_descriptor_get_configuration_sync(daddr, 0, temp_buf, sizeof(temp_buf)))
- {
- parse_config_descriptor(daddr, (tusb_desc_configuration_t*) temp_buf);
+ if (XFER_RESULT_SUCCESS == tuh_descriptor_get_configuration_sync(daddr, 0, temp_buf, sizeof(temp_buf))) {
+ parse_config_descriptor(daddr, (tusb_desc_configuration_t *) temp_buf);
}
}
@@ -171,37 +160,33 @@ uint16_t count_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_
void open_hid_interface(uint8_t daddr, tusb_desc_interface_t const *desc_itf, uint16_t max_len);
// simple configuration parser to open and listen to HID Endpoint IN
-void parse_config_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg)
-{
- uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength);
- uint8_t const* p_desc = tu_desc_next(desc_cfg);
+void parse_config_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const *desc_cfg) {
+ uint8_t const *desc_end = ((uint8_t const *) desc_cfg) + tu_le16toh(desc_cfg->wTotalLength);
+ uint8_t const *p_desc = tu_desc_next(desc_cfg);
// parse each interfaces
- while( p_desc < desc_end )
- {
+ while (p_desc < desc_end) {
uint8_t assoc_itf_count = 1;
// Class will always starts with Interface Association (if any) and then Interface descriptor
- if ( TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc) )
- {
- tusb_desc_interface_assoc_t const * desc_iad = (tusb_desc_interface_assoc_t const *) p_desc;
+ if (TUSB_DESC_INTERFACE_ASSOCIATION == tu_desc_type(p_desc)) {
+ tusb_desc_interface_assoc_t const *desc_iad = (tusb_desc_interface_assoc_t const *) p_desc;
assoc_itf_count = desc_iad->bInterfaceCount;
- p_desc = tu_desc_next(p_desc); // next to Interface
+ p_desc = tu_desc_next(p_desc);// next to Interface
}
// must be interface from now
- if( TUSB_DESC_INTERFACE != tu_desc_type(p_desc) ) return;
- tusb_desc_interface_t const* desc_itf = (tusb_desc_interface_t const*) p_desc;
+ if (TUSB_DESC_INTERFACE != tu_desc_type(p_desc)) { return; }
+ tusb_desc_interface_t const *desc_itf = (tusb_desc_interface_t const *) p_desc;
- uint16_t const drv_len = count_interface_total_len(desc_itf, assoc_itf_count, (uint16_t) (desc_end-p_desc));
+ uint16_t const drv_len = count_interface_total_len(desc_itf, assoc_itf_count, (uint16_t) (desc_end - p_desc));
// probably corrupted descriptor
- if(drv_len < sizeof(tusb_desc_interface_t)) return;
+ if (drv_len < sizeof(tusb_desc_interface_t)) { return; }
// only open and listen to HID endpoint IN
- if (desc_itf->bInterfaceClass == TUSB_CLASS_HID)
- {
+ if (desc_itf->bInterfaceClass == TUSB_CLASS_HID) {
open_hid_interface(dev_addr, desc_itf, drv_len);
}
@@ -210,25 +195,21 @@ void parse_config_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const*
}
}
-uint16_t count_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_t itf_count, uint16_t max_len)
-{
- uint8_t const* p_desc = (uint8_t const*) desc_itf;
+uint16_t count_interface_total_len(tusb_desc_interface_t const *desc_itf, uint8_t itf_count, uint16_t max_len) {
+ uint8_t const *p_desc = (uint8_t const *) desc_itf;
uint16_t len = 0;
- while (itf_count--)
- {
+ while (itf_count--) {
// Next on interface desc
len += tu_desc_len(desc_itf);
p_desc = tu_desc_next(p_desc);
- while (len < max_len)
- {
+ while (len < max_len) {
// return on IAD regardless of itf count
- if ( tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION ) return len;
+ if (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE_ASSOCIATION) { return len; }
- if ( (tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) &&
- ((tusb_desc_interface_t const*) p_desc)->bAlternateSetting == 0 )
- {
+ if ((tu_desc_type(p_desc) == TUSB_DESC_INTERFACE) &&
+ ((tusb_desc_interface_t const *) p_desc)->bAlternateSetting == 0) {
break;
}
@@ -246,46 +227,45 @@ uint16_t count_interface_total_len(tusb_desc_interface_t const* desc_itf, uint8_
void hid_report_received(tuh_xfer_t* xfer);
-void open_hid_interface(uint8_t daddr, tusb_desc_interface_t const *desc_itf, uint16_t max_len)
-{
+void open_hid_interface(uint8_t daddr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) {
// len = interface + hid + n*endpoints
uint16_t const drv_len = (uint16_t) (sizeof(tusb_desc_interface_t) + sizeof(tusb_hid_descriptor_hid_t) +
desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t));
// corrupted descriptor
- if (max_len < drv_len) return;
+ if (max_len < drv_len) { return; }
uint8_t const *p_desc = (uint8_t const *) desc_itf;
// HID descriptor
p_desc = tu_desc_next(p_desc);
tusb_hid_descriptor_hid_t const *desc_hid = (tusb_hid_descriptor_hid_t const *) p_desc;
- if(HID_DESC_TYPE_HID != desc_hid->bDescriptorType) return;
+ if (HID_DESC_TYPE_HID != desc_hid->bDescriptorType) { return; }
// Endpoint descriptor
p_desc = tu_desc_next(p_desc);
- tusb_desc_endpoint_t const * desc_ep = (tusb_desc_endpoint_t const *) p_desc;
+ tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) p_desc;
- for(int i = 0; i < desc_itf->bNumEndpoints; i++)
- {
- if (TUSB_DESC_ENDPOINT != desc_ep->bDescriptorType) return;
+ for (int i = 0; i < desc_itf->bNumEndpoints; i++) {
+ if (TUSB_DESC_ENDPOINT != desc_ep->bDescriptorType) { return; }
- if(tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN)
- {
- // skip if failed to open endpoint
- if ( ! tuh_edpt_open(daddr, desc_ep) ) return;
+ if (tu_edpt_dir(desc_ep->bEndpointAddress) == TUSB_DIR_IN) {
+ if (!tuh_edpt_open(daddr, desc_ep)) {
+ return; // skip if failed to open endpoint
+ }
- uint8_t* buf = get_hid_buf(daddr);
- if (!buf) return; // out of memory
+ uint8_t *buf = get_hid_buf(daddr);
+ if (!buf) {
+ return;// out of memory
+ }
- tuh_xfer_t xfer =
- {
- .daddr = daddr,
- .ep_addr = desc_ep->bEndpointAddress,
- .buflen = 64,
- .buffer = buf,
- .complete_cb = hid_report_received,
- .user_data = (uintptr_t) buf, // since buffer is not available in callback, use user data to store the buffer
+ tuh_xfer_t xfer = {
+ .daddr = daddr,
+ .ep_addr = desc_ep->bEndpointAddress,
+ .buflen = 64,
+ .buffer = buf,
+ .complete_cb = hid_report_received,
+ .user_data = (uintptr_t) buf,// since buffer is not available in callback, use user data to store the buffer
};
// submit transfer for this EP
@@ -299,18 +279,17 @@ void open_hid_interface(uint8_t daddr, tusb_desc_interface_t const *desc_itf, ui
}
}
-void hid_report_received(tuh_xfer_t* xfer)
-{
+void hid_report_received(tuh_xfer_t *xfer) {
// Note: not all field in xfer is available for use (i.e filled by tinyusb stack) in callback to save sram
// For instance, xfer->buffer is NULL. We have used user_data to store buffer when submitted callback
- uint8_t* buf = (uint8_t*) xfer->user_data;
+ uint8_t *buf = (uint8_t *) xfer->user_data;
- if (xfer->result == XFER_RESULT_SUCCESS)
- {
+ if (xfer->result == XFER_RESULT_SUCCESS) {
printf("[dev %u: ep %02x] HID Report:", xfer->daddr, xfer->ep_addr);
- for(uint32_t i=0; iactual_len; i++)
- {
- if (i%16 == 0) printf("\r\n ");
+ for (uint32_t i = 0; i < xfer->actual_len; i++) {
+ if (i % 16 == 0) {
+ printf("\r\n ");
+ }
printf("%02X ", buf[i]);
}
printf("\r\n");
@@ -329,12 +308,9 @@ void hid_report_received(tuh_xfer_t* xfer)
//--------------------------------------------------------------------+
// get an buffer from pool
-uint8_t* get_hid_buf(uint8_t daddr)
-{
- for(size_t i=0; i> 6 & 0x1F));
- *utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F));
- } else {
- // TODO: Verify surrogate.
- *utf8++ = (uint8_t)(0xE0 | (chr >> 12 & 0x0F));
- *utf8++ = (uint8_t)(0x80 | (chr >> 6 & 0x3F));
- *utf8++ = (uint8_t)(0x80 | (chr >> 0 & 0x3F));
- }
- // TODO: Handle UTF-16 code points that take two entries.
+ for (size_t i = 0; i < utf16_len; i++) {
+ uint16_t chr = utf16[i];
+ if (chr < 0x80) {
+ *utf8++ = chr & 0xffu;
+ } else if (chr < 0x800) {
+ *utf8++ = (uint8_t) (0xC0 | (chr >> 6 & 0x1F));
+ *utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F));
+ } else {
+ // TODO: Verify surrogate.
+ *utf8++ = (uint8_t) (0xE0 | (chr >> 12 & 0x0F));
+ *utf8++ = (uint8_t) (0x80 | (chr >> 6 & 0x3F));
+ *utf8++ = (uint8_t) (0x80 | (chr >> 0 & 0x3F));
}
+ // TODO: Handle UTF-16 code points that take two entries.
+ }
}
// Count how many bytes a utf-16-le encoded string will take in utf-8.
static int _count_utf8_bytes(const uint16_t *buf, size_t len) {
- size_t total_bytes = 0;
- for (size_t i = 0; i < len; i++) {
- uint16_t chr = buf[i];
- if (chr < 0x80) {
- total_bytes += 1;
- } else if (chr < 0x800) {
- total_bytes += 2;
- } else {
- total_bytes += 3;
- }
- // TODO: Handle UTF-16 code points that take two entries.
+ size_t total_bytes = 0;
+ for (size_t i = 0; i < len; i++) {
+ uint16_t chr = buf[i];
+ if (chr < 0x80) {
+ total_bytes += 1;
+ } else if (chr < 0x800) {
+ total_bytes += 2;
+ } else {
+ total_bytes += 3;
}
- return (int) total_bytes;
+ // TODO: Handle UTF-16 code points that take two entries.
+ }
+ return (int) total_bytes;
}
static void print_utf16(uint16_t *temp_buf, size_t buf_len) {
- if ((temp_buf[0] & 0xff) == 0) return; // empty
- size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t);
- size_t utf8_len = (size_t) _count_utf8_bytes(temp_buf + 1, utf16_len);
- _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len);
- ((uint8_t*) temp_buf)[utf8_len] = '\0';
+ if ((temp_buf[0] & 0xff) == 0) return;// empty
+ size_t utf16_len = ((temp_buf[0] & 0xff) - 2) / sizeof(uint16_t);
+ size_t utf8_len = (size_t) _count_utf8_bytes(temp_buf + 1, utf16_len);
+ _convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len);
+ ((uint8_t *) temp_buf)[utf8_len] = '\0';
- printf("%s", (char*)temp_buf);
+ printf("%s", (char *) temp_buf);
}
diff --git a/examples/host/bare_api/src/tusb_config.h b/examples/host/bare_api/src/tusb_config.h
index fab233be0..a03675c5f 100644
--- a/examples/host/bare_api/src/tusb_config.h
+++ b/examples/host/bare_api/src/tusb_config.h
@@ -69,9 +69,10 @@
// Enable Host stack
#define CFG_TUH_ENABLED 1
+// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
+
#if CFG_TUSB_MCU == OPT_MCU_RP2040
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
- // #define CFG_TUH_MAX3421 1 // use max3421 as host controller
// host roothub port is 1 if using either pio-usb or max3421
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
diff --git a/examples/host/cdc_msc_hid/CMakePresets.json b/examples/host/cdc_msc_hid/CMakePresets.json
new file mode 100644
index 000000000..5cd8971e9
--- /dev/null
+++ b/examples/host/cdc_msc_hid/CMakePresets.json
@@ -0,0 +1,6 @@
+{
+ "version": 6,
+ "include": [
+ "../../../hw/bsp/BoardPresets.json"
+ ]
+}
diff --git a/examples/host/cdc_msc_hid/src/cdc_app.c b/examples/host/cdc_msc_hid/src/cdc_app.c
index 4a13f8b27..e68ec383b 100644
--- a/examples/host/cdc_msc_hid/src/cdc_app.c
+++ b/examples/host/cdc_msc_hid/src/cdc_app.c
@@ -27,7 +27,7 @@
#include "tusb.h"
#include "bsp/board_api.h"
-size_t get_console_inputs(uint8_t* buf, size_t bufsize) {
+static size_t get_console_inputs(uint8_t* buf, size_t bufsize) {
size_t count = 0;
while (count < bufsize) {
int ch = board_getchar();
diff --git a/examples/host/cdc_msc_hid/src/hid_app.c b/examples/host/cdc_msc_hid/src/hid_app.c
index 3f98ec89f..a751c9c80 100644
--- a/examples/host/cdc_msc_hid/src/hid_app.c
+++ b/examples/host/cdc_msc_hid/src/hid_app.c
@@ -39,18 +39,16 @@
static uint8_t const keycode2ascii[128][2] = { HID_KEYCODE_TO_ASCII };
// Each HID instance can has multiple reports
-static struct
-{
+static struct {
uint8_t report_count;
tuh_hid_report_info_t report_info[MAX_REPORT];
-}hid_info[CFG_TUH_HID];
+} hid_info[CFG_TUH_HID];
static void process_kbd_report(hid_keyboard_report_t const *report);
static void process_mouse_report(hid_mouse_report_t const * report);
static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len);
-void hid_app_task(void)
-{
+void hid_app_task(void) {
// nothing to do
}
@@ -63,64 +61,57 @@ void hid_app_task(void)
// can be used to parse common/simple enough descriptor.
// Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped
// therefore report_desc = NULL, desc_len = 0
-void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_report, uint16_t desc_len)
-{
+void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *desc_report, uint16_t desc_len) {
printf("HID device address = %d, instance = %d is mounted\r\n", dev_addr, instance);
// Interface protocol (hid_interface_protocol_enum_t)
- const char* protocol_str[] = { "None", "Keyboard", "Mouse" };
+ const char *protocol_str[] = {"None", "Keyboard", "Mouse"};
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
printf("HID Interface Protocol = %s\r\n", protocol_str[itf_protocol]);
// By default host stack will use activate boot protocol on supported interface.
// Therefore for this simple example, we only need to parse generic report descriptor (with built-in parser)
- if ( itf_protocol == HID_ITF_PROTOCOL_NONE )
- {
+ if (itf_protocol == HID_ITF_PROTOCOL_NONE) {
hid_info[instance].report_count = tuh_hid_parse_report_descriptor(hid_info[instance].report_info, MAX_REPORT, desc_report, desc_len);
printf("HID has %u reports \r\n", hid_info[instance].report_count);
}
// request to receive report
// tuh_hid_report_received_cb() will be invoked when report is available
- if ( !tuh_hid_receive_report(dev_addr, instance) )
- {
+ if (!tuh_hid_receive_report(dev_addr, instance)) {
printf("Error: cannot request to receive report\r\n");
}
}
// Invoked when device with hid interface is un-mounted
-void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
-{
+void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance) {
printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
}
// Invoked when received report from device via interrupt endpoint
-void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
-{
+void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
uint8_t const itf_protocol = tuh_hid_interface_protocol(dev_addr, instance);
- switch (itf_protocol)
- {
+ switch (itf_protocol) {
case HID_ITF_PROTOCOL_KEYBOARD:
TU_LOG2("HID receive boot keyboard report\r\n");
- process_kbd_report( (hid_keyboard_report_t const*) report );
- break;
+ process_kbd_report((hid_keyboard_report_t const *) report);
+ break;
case HID_ITF_PROTOCOL_MOUSE:
TU_LOG2("HID receive boot mouse report\r\n");
- process_mouse_report( (hid_mouse_report_t const*) report );
- break;
+ process_mouse_report((hid_mouse_report_t const *) report);
+ break;
default:
// Generic report requires matching ReportID and contents with previous parsed report info
process_generic_report(dev_addr, instance, report, len);
- break;
+ break;
}
// continue to request to receive report
- if ( !tuh_hid_receive_report(dev_addr, instance) )
- {
+ if (!tuh_hid_receive_report(dev_addr, instance)) {
printf("Error: cannot request to receive report\r\n");
}
}
@@ -174,8 +165,7 @@ static void process_kbd_report(hid_keyboard_report_t const *report)
// Mouse
//--------------------------------------------------------------------+
-void cursor_movement(int8_t x, int8_t y, int8_t wheel)
-{
+static void cursor_movement(int8_t x, int8_t y, int8_t wheel) {
#if USE_ANSI_ESCAPE
// Move X using ansi escape
if ( x < 0)
@@ -231,29 +221,24 @@ static void process_mouse_report(hid_mouse_report_t const * report)
//--------------------------------------------------------------------+
// Generic Report
//--------------------------------------------------------------------+
-static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
-{
+static void process_generic_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
(void) dev_addr;
(void) len;
uint8_t const rpt_count = hid_info[instance].report_count;
- tuh_hid_report_info_t* rpt_info_arr = hid_info[instance].report_info;
- tuh_hid_report_info_t* rpt_info = NULL;
+ tuh_hid_report_info_t *rpt_info_arr = hid_info[instance].report_info;
+ tuh_hid_report_info_t *rpt_info = NULL;
- if ( rpt_count == 1 && rpt_info_arr[0].report_id == 0)
- {
+ if (rpt_count == 1 && rpt_info_arr[0].report_id == 0) {
// Simple report without report ID as 1st byte
rpt_info = &rpt_info_arr[0];
- }else
- {
+ } else {
// Composite report, 1st byte is report ID, data starts from 2nd byte
uint8_t const rpt_id = report[0];
// Find report id in the array
- for(uint8_t i=0; iusage_page == HID_USAGE_PAGE_DESKTOP )
- {
- switch (rpt_info->usage)
- {
+ if (rpt_info->usage_page == HID_USAGE_PAGE_DESKTOP) {
+ switch (rpt_info->usage) {
case HID_USAGE_DESKTOP_KEYBOARD:
TU_LOG1("HID receive keyboard report\r\n");
// Assume keyboard follow boot report layout
- process_kbd_report( (hid_keyboard_report_t const*) report );
- break;
+ process_kbd_report((hid_keyboard_report_t const *) report);
+ break;
case HID_USAGE_DESKTOP_MOUSE:
TU_LOG1("HID receive mouse report\r\n");
// Assume mouse follow boot report layout
- process_mouse_report( (hid_mouse_report_t const*) report );
- break;
+ process_mouse_report((hid_mouse_report_t const *) report);
+ break;
- default: break;
+ default:
+ break;
}
}
}
diff --git a/examples/host/cdc_msc_hid/src/main.c b/examples/host/cdc_msc_hid/src/main.c
index 71257c0fe..7b02e238e 100644
--- a/examples/host/cdc_msc_hid/src/main.c
+++ b/examples/host/cdc_msc_hid/src/main.c
@@ -31,18 +31,12 @@
#include "tusb.h"
//--------------------------------------------------------------------+
-// MACRO CONSTANT TYPEDEF PROTYPES
+// MACRO CONSTANT TYPEDEF PROTOTYPES
//--------------------------------------------------------------------+
void led_blinking_task(void);
extern void cdc_app_task(void);
extern void hid_app_task(void);
-#if CFG_TUH_ENABLED && CFG_TUH_MAX3421
-// API to read/rite MAX3421's register. Implemented by TinyUSB
-extern uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr);
-extern bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr);
-#endif
-
/*------------- MAIN -------------*/
int main(void) {
board_init();
@@ -82,12 +76,12 @@ int main(void) {
void tuh_mount_cb(uint8_t dev_addr) {
// application set-up
- printf("A device with address %d is mounted\r\n", dev_addr);
+ printf("A device with address %u is mounted\r\n", dev_addr);
}
void tuh_umount_cb(uint8_t dev_addr) {
// application tear-down
- printf("A device with address %d is unmounted \r\n", dev_addr);
+ printf("A device with address %u is unmounted \r\n", dev_addr);
}
@@ -101,7 +95,9 @@ void led_blinking_task(void) {
static bool led_state = false;
// Blink every interval ms
- if (board_millis() - start_ms < interval_ms) return; // not enough time
+ if (board_millis() - start_ms < interval_ms) {
+ return;// not enough time
+ }
start_ms += interval_ms;
board_led_write(led_state);
diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h
index a59a0ffb9..cc8d6e5c4 100644
--- a/examples/host/cdc_msc_hid/src/tusb_config.h
+++ b/examples/host/cdc_msc_hid/src/tusb_config.h
@@ -69,9 +69,10 @@
// Enable Host stack
#define CFG_TUH_ENABLED 1
+// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
+
#if CFG_TUSB_MCU == OPT_MCU_RP2040
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
- // #define CFG_TUH_MAX3421 1 // use max3421 as host controller
// host roothub port is 1 if using either pio-usb or max3421
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
diff --git a/examples/host/cdc_msc_hid_freertos/CMakePresets.json b/examples/host/cdc_msc_hid_freertos/CMakePresets.json
new file mode 100644
index 000000000..5cd8971e9
--- /dev/null
+++ b/examples/host/cdc_msc_hid_freertos/CMakePresets.json
@@ -0,0 +1,6 @@
+{
+ "version": 6,
+ "include": [
+ "../../../hw/bsp/BoardPresets.json"
+ ]
+}
diff --git a/examples/host/cdc_msc_hid_freertos/Makefile b/examples/host/cdc_msc_hid_freertos/Makefile
index 67fbb9af3..178341f81 100644
--- a/examples/host/cdc_msc_hid_freertos/Makefile
+++ b/examples/host/cdc_msc_hid_freertos/Makefile
@@ -1,14 +1,9 @@
+RTOS = freertos
include ../../build_system/make/make.mk
-FREERTOS_SRC = lib/FreeRTOS-Kernel
-FREERTOS_PORTABLE_PATH= $(FREERTOS_SRC)/portable/$(if $(findstring iar,$(TOOLCHAIN)),IAR,GCC)
-
INC += \
src \
- src/FreeRTOSConfig \
$(TOP)/hw \
- $(TOP)/$(FREERTOS_SRC)/include \
- $(TOP)/$(FREERTOS_PORTABLE_SRC) \
# Example source
EXAMPLE_SOURCE = \
@@ -19,15 +14,4 @@ EXAMPLE_SOURCE = \
SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
-# FreeRTOS source, all files in port folder
-SRC_C += \
- $(FREERTOS_SRC)/list.c \
- $(FREERTOS_SRC)/queue.c \
- $(FREERTOS_SRC)/tasks.c \
- $(FREERTOS_SRC)/timers.c \
- $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.c))
-
-SRC_S += \
- $(subst $(TOP)/,,$(wildcard $(TOP)/$(FREERTOS_PORTABLE_SRC)/*.s))
-
include ../../build_system/make/rules.mk
diff --git a/examples/host/cdc_msc_hid_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h b/examples/host/cdc_msc_hid_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
deleted file mode 100644
index 6a886adec..000000000
--- a/examples/host/cdc_msc_hid_freertos/src/FreeRTOSConfig/FreeRTOSConfig.h
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * FreeRTOS Kernel V10.0.0
- * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
- *
- * 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. If you wish to use our Amazon
- * FreeRTOS name, please do so in a fair use way that does not cause confusion.
- *
- * 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.
- *
- * http://www.FreeRTOS.org
- * http://aws.amazon.com/freertos
- *
- * 1 tab == 4 spaces!
- */
-
-
-#ifndef FREERTOS_CONFIG_H
-#define FREERTOS_CONFIG_H
-
-/*-----------------------------------------------------------
- * Application specific definitions.
- *
- * These definitions should be adjusted for your particular hardware and
- * application requirements.
- *
- * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
- * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
- *
- * See http://www.freertos.org/a00110.html.
- *----------------------------------------------------------*/
-
-// skip if included from IAR assembler
-#ifndef __IASMARM__
-
-// Include MCU header
-#include "bsp/board_mcu.h"
-
-#if TUSB_MCU_VENDOR_ESPRESSIF
- #error "ESP32-Sx should use IDF's FreeRTOSConfig.h"
-#endif
-
-#ifdef __GNUC__
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wredundant-decls"
-#endif
-
-// TODO fix later
-// FIXME cause redundant-decls warnings
-#if CFG_TUSB_MCU == OPT_MCU_MM32F327X
- extern u32 SystemCoreClock;
-#else
- extern uint32_t SystemCoreClock;
-#endif
-
-#ifdef __GNUC__
-#pragma GCC diagnostic pop
-#endif
-
-#endif
-
-/* Cortex M23/M33 port configuration. */
-#define configENABLE_MPU 0
-#define configENABLE_FPU 1
-#define configENABLE_TRUSTZONE 0
-#define configMINIMAL_SECURE_STACK_SIZE ( 1024 )
-
-#define configUSE_PREEMPTION 1
-#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
-#define configCPU_CLOCK_HZ SystemCoreClock
-#define configTICK_RATE_HZ ( 1000 )
-#define configMAX_PRIORITIES ( 5 )
-#define configMINIMAL_STACK_SIZE ( 128 )
-#define configTOTAL_HEAP_SIZE ( configSUPPORT_DYNAMIC_ALLOCATION*4*1024 )
-#define configMAX_TASK_NAME_LEN 16
-#define configUSE_16_BIT_TICKS 0
-#define configIDLE_SHOULD_YIELD 1
-#define configUSE_MUTEXES 1
-#define configUSE_RECURSIVE_MUTEXES 1
-#define configUSE_COUNTING_SEMAPHORES 1
-#define configQUEUE_REGISTRY_SIZE 4
-#define configUSE_QUEUE_SETS 0
-#define configUSE_TIME_SLICING 0
-#define configUSE_NEWLIB_REENTRANT 0
-#define configENABLE_BACKWARD_COMPATIBILITY 1
-#define configSTACK_ALLOCATION_FROM_SEPARATE_HEAP 0
-
-#define configSUPPORT_STATIC_ALLOCATION 1
-#define configSUPPORT_DYNAMIC_ALLOCATION 0
-
-/* Hook function related definitions. */
-#define configUSE_IDLE_HOOK 0
-#define configUSE_TICK_HOOK 0
-#define configUSE_MALLOC_FAILED_HOOK 0 // cause nested extern warning
-#define configCHECK_FOR_STACK_OVERFLOW 2
-#define configCHECK_HANDLER_INSTALLATION 0
-
-/* Run time and task stats gathering related definitions. */
-#define configGENERATE_RUN_TIME_STATS 0
-#define configUSE_TRACE_FACILITY 1 // legacy trace
-#define configUSE_STATS_FORMATTING_FUNCTIONS 0
-
-/* Co-routine definitions. */
-#define configUSE_CO_ROUTINES 0
-#define configMAX_CO_ROUTINE_PRIORITIES 2
-
-/* Software timer related definitions. */
-#define configUSE_TIMERS 1
-#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-2)
-#define configTIMER_QUEUE_LENGTH 32
-#define configTIMER_TASK_STACK_DEPTH configMINIMAL_STACK_SIZE
-
-/* Optional functions - most linkers will remove unused functions anyway. */
-#define INCLUDE_vTaskPrioritySet 0
-#define INCLUDE_uxTaskPriorityGet 0
-#define INCLUDE_vTaskDelete 0
-#define INCLUDE_vTaskSuspend 1 // required for queue, semaphore, mutex to be blocked indefinitely with portMAX_DELAY
-#define INCLUDE_xResumeFromISR 0
-#define INCLUDE_vTaskDelayUntil 1
-#define INCLUDE_vTaskDelay 1
-#define INCLUDE_xTaskGetSchedulerState 0
-#define INCLUDE_xTaskGetCurrentTaskHandle 0
-#define INCLUDE_uxTaskGetStackHighWaterMark 0
-#define INCLUDE_xTaskGetIdleTaskHandle 0
-#define INCLUDE_xTimerGetTimerDaemonTaskHandle 0
-#define INCLUDE_pcTaskGetTaskName 0
-#define INCLUDE_eTaskGetState 0
-#define INCLUDE_xEventGroupSetBitFromISR 0
-#define INCLUDE_xTimerPendFunctionCall 0
-
-#ifdef __RX__
-/* Renesas RX series */
-#define vSoftwareInterruptISR INT_Excep_ICU_SWINT
-#define vTickISR INT_Excep_CMT0_CMI0
-#define configPERIPHERAL_CLOCK_HZ (configCPU_CLOCK_HZ/2)
-#define configKERNEL_INTERRUPT_PRIORITY 1
-#define configMAX_SYSCALL_INTERRUPT_PRIORITY 4
-
-#else
-
-/* FreeRTOS hooks to NVIC vectors */
-#define xPortPendSVHandler PendSV_Handler
-#define xPortSysTickHandler SysTick_Handler
-#define vPortSVCHandler SVC_Handler
-
-//--------------------------------------------------------------------+
-// Interrupt nesting behavior configuration.
-//--------------------------------------------------------------------+
-#if defined(__NVIC_PRIO_BITS)
- // For Cortex-M specific: __NVIC_PRIO_BITS is defined in core_cmx.h
- #define configPRIO_BITS __NVIC_PRIO_BITS
-
-#elif defined(__ECLIC_INTCTLBITS)
- // RISC-V Bumblebee core from nuclei
- #define configPRIO_BITS __ECLIC_INTCTLBITS
-
-#elif defined(__IASMARM__)
- // FIXME: IAR Assembler cannot include mcu header directly to get __NVIC_PRIO_BITS.
- // Therefore we will hard coded it to minimum value of 2 to get pass ci build.
- // IAR user must update this to correct value of the target MCU
- #message "configPRIO_BITS is hard coded to 2 to pass IAR build only. User should update it per MCU"
- #define configPRIO_BITS 2
-
-#else
- #error "FreeRTOS configPRIO_BITS to be defined"
-#endif
-
-/* The lowest interrupt priority that can be used in a call to a "set priority" function. */
-#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY ((1<cbw;
msc_csw_t const *csw = cb_data->csw;
diff --git a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h
index 02de4197b..682265f59 100644
--- a/examples/host/cdc_msc_hid_freertos/src/tusb_config.h
+++ b/examples/host/cdc_msc_hid_freertos/src/tusb_config.h
@@ -74,9 +74,10 @@
// Enable Host stack
#define CFG_TUH_ENABLED 1
+// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
+
#if CFG_TUSB_MCU == OPT_MCU_RP2040
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
- // #define CFG_TUH_MAX3421 1 // use max3421 as host controller
// host roothub port is 1 if using either pio-usb or max3421
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
diff --git a/examples/host/device_info/CMakePresets.json b/examples/host/device_info/CMakePresets.json
new file mode 100644
index 000000000..5cd8971e9
--- /dev/null
+++ b/examples/host/device_info/CMakePresets.json
@@ -0,0 +1,6 @@
+{
+ "version": 6,
+ "include": [
+ "../../../hw/bsp/BoardPresets.json"
+ ]
+}
diff --git a/examples/host/device_info/src/main.c b/examples/host/device_info/src/main.c
index 775968c16..e924a137b 100644
--- a/examples/host/device_info/src/main.c
+++ b/examples/host/device_info/src/main.c
@@ -81,7 +81,7 @@ void init_freertos_task(void);
//--------------------------------------------------------------------
// Main
//--------------------------------------------------------------------
-void init_tinyusb(void) {
+static void init_tinyusb(void) {
// init host stack on configured roothub port
tusb_rhport_init_t host_init = {
.role = TUSB_ROLE_HOST,
@@ -124,13 +124,18 @@ void tuh_mount_cb(uint8_t daddr) {
}
printf("Device %u: ID %04x:%04x SN ", daddr, desc.device.idVendor, desc.device.idProduct);
- xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, desc.serial, sizeof(desc.serial));
+
+ xfer_result = XFER_RESULT_FAILED;
+ if (desc.device.iSerialNumber != 0) {
+ xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, desc.serial, sizeof(desc.serial));
+ }
if (XFER_RESULT_SUCCESS != xfer_result) {
uint16_t* serial = (uint16_t*)(uintptr_t) desc.serial;
- serial[0] = 'n';
- serial[1] = '/';
- serial[2] = 'a';
- serial[3] = 0;
+ serial[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * 3 + 2));
+ serial[1] = 'n';
+ serial[2] = '/';
+ serial[3] = 'a';
+ serial[4] = 0;
}
print_utf16((uint16_t*)(uintptr_t) desc.serial, sizeof(desc.serial)/2);
printf("\r\n");
@@ -150,16 +155,20 @@ void tuh_mount_cb(uint8_t daddr) {
// Get String descriptor using Sync API
printf(" iManufacturer %u ", desc.device.iManufacturer);
- xfer_result = tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, desc.buf, sizeof(desc.buf));
- if (XFER_RESULT_SUCCESS == xfer_result) {
- print_utf16((uint16_t*)(uintptr_t) desc.buf, sizeof(desc.buf)/2);
+ if (desc.device.iManufacturer != 0) {
+ xfer_result = tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, desc.buf, sizeof(desc.buf));
+ if (XFER_RESULT_SUCCESS == xfer_result) {
+ print_utf16((uint16_t*)(uintptr_t) desc.buf, sizeof(desc.buf)/2);
+ }
}
printf("\r\n");
printf(" iProduct %u ", desc.device.iProduct);
- xfer_result = tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, desc.buf, sizeof(desc.buf));
- if (XFER_RESULT_SUCCESS == xfer_result) {
- print_utf16((uint16_t*)(uintptr_t) desc.buf, sizeof(desc.buf)/2);
+ if (desc.device.iProduct != 0) {
+ xfer_result = tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, desc.buf, sizeof(desc.buf));
+ if (XFER_RESULT_SUCCESS == xfer_result) {
+ print_utf16((uint16_t*)(uintptr_t) desc.buf, sizeof(desc.buf)/2);
+ }
}
printf("\r\n");
diff --git a/examples/host/device_info/src/tusb_config.h b/examples/host/device_info/src/tusb_config.h
index 5190b5b1f..e12970c12 100644
--- a/examples/host/device_info/src/tusb_config.h
+++ b/examples/host/device_info/src/tusb_config.h
@@ -74,9 +74,10 @@
// Enable Host stack
#define CFG_TUH_ENABLED 1
+// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
+
#if CFG_TUSB_MCU == OPT_MCU_RP2040
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
- // #define CFG_TUH_MAX3421 1 // use max3421 as host controller
// host roothub port is 1 if using either pio-usb or max3421
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
@@ -109,8 +110,7 @@
// only hub class is enabled
#define CFG_TUH_HUB 1
-// max device support (excluding hub device)
-// 1 hub typically has 4 ports
+// max device support (excluding hub device): 1 hub typically has 4 ports
#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
#ifdef __cplusplus
diff --git a/examples/host/hid_controller/CMakePresets.json b/examples/host/hid_controller/CMakePresets.json
new file mode 100644
index 000000000..5cd8971e9
--- /dev/null
+++ b/examples/host/hid_controller/CMakePresets.json
@@ -0,0 +1,6 @@
+{
+ "version": 6,
+ "include": [
+ "../../../hw/bsp/BoardPresets.json"
+ ]
+}
diff --git a/examples/host/hid_controller/src/hid_app.c b/examples/host/hid_controller/src/hid_app.c
index 6ffe0b6d4..1d6ca8b07 100644
--- a/examples/host/hid_controller/src/hid_app.c
+++ b/examples/host/hid_controller/src/hid_app.c
@@ -231,14 +231,12 @@ void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
}
// check if different than 2
-bool diff_than_2(uint8_t x, uint8_t y)
-{
+static inline bool diff_than_2(uint8_t x, uint8_t y) {
return (x - y > 2) || (y - x > 2);
}
// check if 2 reports are different enough
-bool diff_report(sony_ds4_report_t const* rpt1, sony_ds4_report_t const* rpt2)
-{
+static bool diff_report(sony_ds4_report_t const* rpt1, sony_ds4_report_t const* rpt2) {
bool result;
// x, y, z, rz must different than 2 to be counted
@@ -251,7 +249,7 @@ bool diff_report(sony_ds4_report_t const* rpt1, sony_ds4_report_t const* rpt2)
return result;
}
-void process_sony_ds4(uint8_t const* report, uint16_t len)
+static void process_sony_ds4(uint8_t const* report, uint16_t len)
{
(void)len;
const char* dpad_str[] = { "N", "NE", "E", "SE", "S", "SW", "W", "NW", "none" };
@@ -310,16 +308,13 @@ void process_sony_ds4(uint8_t const* report, uint16_t len)
}
// Invoked when received report from device via interrupt endpoint
-void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* report, uint16_t len)
-{
- if ( is_sony_ds4(dev_addr) )
- {
+void tuh_hid_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) {
+ if (is_sony_ds4(dev_addr)) {
process_sony_ds4(report, len);
}
// continue to request to receive report
- if ( !tuh_hid_receive_report(dev_addr, instance) )
- {
+ if (!tuh_hid_receive_report(dev_addr, instance)) {
printf("Error: cannot request to receive report\r\n");
}
}
diff --git a/examples/host/hid_controller/src/tusb_config.h b/examples/host/hid_controller/src/tusb_config.h
index 3ac591d8f..351fe0178 100644
--- a/examples/host/hid_controller/src/tusb_config.h
+++ b/examples/host/hid_controller/src/tusb_config.h
@@ -69,9 +69,10 @@
// Enable Host stack
#define CFG_TUH_ENABLED 1
+// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
+
#if CFG_TUSB_MCU == OPT_MCU_RP2040
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
- // #define CFG_TUH_MAX3421 1 // use max3421 as host controller
// host roothub port is 1 if using either pio-usb or max3421
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
diff --git a/examples/host/midi_rx/CMakeLists.txt b/examples/host/midi_rx/CMakeLists.txt
new file mode 100644
index 000000000..33953233d
--- /dev/null
+++ b/examples/host/midi_rx/CMakeLists.txt
@@ -0,0 +1,32 @@
+cmake_minimum_required(VERSION 3.20)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
+
+# gets PROJECT name for the example
+family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
+
+project(${PROJECT} C CXX ASM)
+
+# Checks this example is valid for the family and initializes the project
+family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
+
+# Espressif has its own cmake build system
+if(FAMILY STREQUAL "espressif")
+ return()
+endif()
+
+add_executable(${PROJECT})
+
+# Example source
+target_sources(${PROJECT} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
+ )
+
+# Example include
+target_include_directories(${PROJECT} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ )
+
+# Configure compilation flags and libraries for the example without RTOS.
+# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
+family_configure_host_example(${PROJECT} noos)
diff --git a/examples/host/midi_rx/Makefile b/examples/host/midi_rx/Makefile
new file mode 100644
index 000000000..0235e08c3
--- /dev/null
+++ b/examples/host/midi_rx/Makefile
@@ -0,0 +1,13 @@
+include ../../build_system/make/make.mk
+
+INC += \
+ src \
+ $(TOP)/hw \
+
+# Example source
+EXAMPLE_SOURCE += \
+ src/main.c
+
+SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
+
+include ../../build_system/make/rules.mk
diff --git a/examples/host/midi_rx/only.txt b/examples/host/midi_rx/only.txt
new file mode 100644
index 000000000..b6f87f423
--- /dev/null
+++ b/examples/host/midi_rx/only.txt
@@ -0,0 +1,20 @@
+mcu:ESP32S2
+mcu:ESP32S3
+mcu:ESP32P4
+mcu:KINETIS_KL
+mcu:LPC175X_6X
+mcu:LPC177X_8X
+mcu:LPC18XX
+mcu:LPC40XX
+mcu:LPC43XX
+mcu:MAX3421
+mcu:MIMXRT1XXX
+mcu:MIMXRT10XX
+mcu:MIMXRT11XX
+mcu:MSP432E4
+mcu:RP2040
+mcu:RX65X
+mcu:RAXXX
+mcu:STM32F4
+mcu:STM32F7
+mcu:STM32H7
diff --git a/examples/host/midi_rx/src/main.c b/examples/host/midi_rx/src/main.c
new file mode 100644
index 000000000..78b1a11b9
--- /dev/null
+++ b/examples/host/midi_rx/src/main.c
@@ -0,0 +1,123 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include
+#include
+#include
+
+#include "bsp/board_api.h"
+#include "tusb.h"
+
+//--------------------------------------------------------------------+
+// STATIC GLOBALS DECLARATION
+//--------------------------------------------------------------------+
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF PROTOTYPES
+//--------------------------------------------------------------------+
+void led_blinking_task(void);
+void midi_host_rx_task(void);
+
+/*------------- MAIN -------------*/
+int main(void) {
+ board_init();
+
+ printf("TinyUSB Host MIDI Example\r\n");
+
+ // init host stack on configured roothub port
+ tusb_rhport_init_t host_init = {
+ .role = TUSB_ROLE_HOST,
+ .speed = TUSB_SPEED_AUTO
+ };
+ tusb_init(BOARD_TUH_RHPORT, &host_init);
+
+ while (1) {
+ tuh_task();
+ led_blinking_task();
+ midi_host_rx_task();
+ }
+
+ return 0;
+}
+
+//--------------------------------------------------------------------+
+// Blinking Task
+//--------------------------------------------------------------------+
+void led_blinking_task(void) {
+ const uint32_t interval_ms = 1000;
+ static uint32_t start_ms = 0;
+
+ static bool led_state = false;
+
+ // Blink every interval ms
+ if (board_millis() - start_ms < interval_ms) return;// not enough time
+ start_ms += interval_ms;
+
+ board_led_write(led_state);
+ led_state = 1 - led_state;// toggle
+}
+
+//--------------------------------------------------------------------+
+// MIDI host receive task
+//--------------------------------------------------------------------+
+void midi_host_rx_task(void) {
+ // nothing to do, we just print out received data in callback
+}
+
+//--------------------------------------------------------------------+
+// TinyUSB Callbacks
+//--------------------------------------------------------------------+
+
+// Invoked when device with MIDI interface is mounted.
+void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t* mount_cb_data) {
+ printf("MIDI Interface Index = %u, Address = %u, Number of RX cables = %u, Number of TX cables = %u\r\n",
+ idx, mount_cb_data->daddr, mount_cb_data->rx_cable_count, mount_cb_data->tx_cable_count);
+}
+
+// Invoked when device with hid interface is un-mounted
+void tuh_midi_umount_cb(uint8_t idx) {
+ printf("MIDI Interface Index = %u is unmounted\r\n", idx);
+}
+
+void tuh_midi_rx_cb(uint8_t idx, uint32_t xferred_bytes) {
+ if (xferred_bytes == 0) {
+ return;
+ }
+
+ uint8_t buffer[48];
+ uint8_t cable_num = 0;
+ uint32_t bytes_read = tuh_midi_stream_read(idx, &cable_num, buffer, sizeof(buffer));
+
+ printf("Cable %u rx: ", cable_num);
+ for (uint32_t i = 0; i < bytes_read; i++) {
+ printf("%02X ", buffer[i]);
+ }
+ printf("\r\n");
+}
+
+void tuh_midi_tx_cb(uint8_t idx, uint32_t xferred_bytes) {
+ (void) idx;
+ (void) xferred_bytes;
+}
diff --git a/examples/host/midi_rx/src/tusb_config.h b/examples/host/midi_rx/src/tusb_config.h
new file mode 100644
index 000000000..c9b430388
--- /dev/null
+++ b/examples/host/midi_rx/src/tusb_config.h
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ *
+ */
+
+#ifndef TUSB_CONFIG_H_
+#define TUSB_CONFIG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//--------------------------------------------------------------------
+// Common Configuration
+//--------------------------------------------------------------------
+
+// defined by compiler flags for flexibility
+#ifndef CFG_TUSB_MCU
+#error CFG_TUSB_MCU must be defined
+#endif
+
+// Espressif IDF requires "freertos/" prefix in include path
+#if TUSB_MCU_VENDOR_ESPRESSIF
+#define CFG_TUSB_OS_INC_PATH freertos/
+#endif
+
+#ifndef CFG_TUSB_OS
+#define CFG_TUSB_OS OPT_OS_NONE
+#endif
+
+#ifndef CFG_TUSB_DEBUG
+#define CFG_TUSB_DEBUG 0
+#endif
+
+/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
+ * Tinyusb use follows macros to declare transferring memory so that they can be put
+ * into those specific section.
+ * e.g
+ * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
+ * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
+ */
+#ifndef CFG_TUH_MEM_SECTION
+#define CFG_TUH_MEM_SECTION
+#endif
+
+#ifndef CFG_TUH_MEM_ALIGN
+#define CFG_TUH_MEM_ALIGN __attribute__ ((aligned(4)))
+#endif
+
+//--------------------------------------------------------------------
+// Host Configuration
+//--------------------------------------------------------------------
+
+// Enable Host stack
+#define CFG_TUH_ENABLED 1
+
+#if CFG_TUSB_MCU == OPT_MCU_RP2040
+ // #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
+ // #define CFG_TUH_MAX3421 1 // use max3421 as host controller
+
+ // host roothub port is 1 if using either pio-usb or max3421
+ #if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
+ #define BOARD_TUH_RHPORT 1
+ #endif
+#endif
+
+// Default is max speed that hardware controller could support with on-chip PHY
+#define CFG_TUH_MAX_SPEED BOARD_TUH_MAX_SPEED
+
+//------------------------- Board Specific --------------------------
+
+// RHPort number used for host can be defined by board.mk, default to port 0
+#ifndef BOARD_TUH_RHPORT
+#define BOARD_TUH_RHPORT 0
+#endif
+
+// RHPort max operational speed can defined by board.mk
+#ifndef BOARD_TUH_MAX_SPEED
+#define BOARD_TUH_MAX_SPEED OPT_MODE_DEFAULT_SPEED
+#endif
+
+//--------------------------------------------------------------------
+// Driver Configuration
+//--------------------------------------------------------------------
+
+// Size of buffer to hold descriptors and other data used for enumeration
+#define CFG_TUH_ENUMERATION_BUFSIZE 256
+
+#define CFG_TUH_HUB 1
+// max device support (excluding hub device): 1 hub typically has 4 ports
+#define CFG_TUH_DEVICE_MAX (3*CFG_TUH_HUB + 1)
+#define CFG_TUH_MIDI CFG_TUH_DEVICE_MAX
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/examples/host/msc_file_explorer/CMakePresets.json b/examples/host/msc_file_explorer/CMakePresets.json
new file mode 100644
index 000000000..5cd8971e9
--- /dev/null
+++ b/examples/host/msc_file_explorer/CMakePresets.json
@@ -0,0 +1,6 @@
+{
+ "version": 6,
+ "include": [
+ "../../../hw/bsp/BoardPresets.json"
+ ]
+}
diff --git a/examples/host/msc_file_explorer/src/msc_app.c b/examples/host/msc_file_explorer/src/msc_app.c
index 226c870ea..40a9ef57e 100644
--- a/examples/host/msc_file_explorer/src/msc_app.c
+++ b/examples/host/msc_file_explorer/src/msc_app.c
@@ -34,6 +34,8 @@
#define EMBEDDED_CLI_IMPL
#include "embedded_cli.h"
+#include "msc_app.h"
+
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM DECLARATION
diff --git a/examples/host/msc_file_explorer/src/tusb_config.h b/examples/host/msc_file_explorer/src/tusb_config.h
index c798b4383..c1829c300 100644
--- a/examples/host/msc_file_explorer/src/tusb_config.h
+++ b/examples/host/msc_file_explorer/src/tusb_config.h
@@ -69,9 +69,10 @@
// Enable Host stack
#define CFG_TUH_ENABLED 1
+// #define CFG_TUH_MAX3421 1 // use max3421 as host controller
+
#if CFG_TUSB_MCU == OPT_MCU_RP2040
// #define CFG_TUH_RPI_PIO_USB 1 // use pio-usb as host controller
- // #define CFG_TUH_MAX3421 1 // use max3421 as host controller
// host roothub port is 1 if using either pio-usb or max3421
#if (defined(CFG_TUH_RPI_PIO_USB) && CFG_TUH_RPI_PIO_USB) || (defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421)
diff --git a/examples/typec/CMakePresets.json b/examples/typec/CMakePresets.json
new file mode 100644
index 000000000..c22e8c0ec
--- /dev/null
+++ b/examples/typec/CMakePresets.json
@@ -0,0 +1,6 @@
+{
+ "version": 6,
+ "include": [
+ "../../hw/bsp/BoardPresets.json"
+ ]
+}
diff --git a/examples/typec/power_delivery/CMakePresets.json b/examples/typec/power_delivery/CMakePresets.json
new file mode 100644
index 000000000..5cd8971e9
--- /dev/null
+++ b/examples/typec/power_delivery/CMakePresets.json
@@ -0,0 +1,6 @@
+{
+ "version": 6,
+ "include": [
+ "../../../hw/bsp/BoardPresets.json"
+ ]
+}
diff --git a/hw/bsp/BoardPresets.json b/hw/bsp/BoardPresets.json
new file mode 100644
index 000000000..fee8f2c97
--- /dev/null
+++ b/hw/bsp/BoardPresets.json
@@ -0,0 +1,4002 @@
+{
+ "version": 6,
+ "configurePresets": [
+ {
+ "name": "default",
+ "hidden": true,
+ "description": "Configure preset for the ${presetName} board",
+ "generator": "Ninja Multi-Config",
+ "binaryDir": "${sourceDir}/build/${presetName}",
+ "cacheVariables": {
+ "CMAKE_DEFAULT_BUILD_TYPE": "RelWithDebInfo",
+ "BOARD": "${presetName}"
+ }
+ },
+ {
+ "name": "adafruit_clue",
+ "inherits": "default"
+ },
+ {
+ "name": "adafruit_feather_esp32_v2",
+ "inherits": "default"
+ },
+ {
+ "name": "adafruit_feather_esp32s2",
+ "inherits": "default"
+ },
+ {
+ "name": "adafruit_feather_esp32s3",
+ "inherits": "default"
+ },
+ {
+ "name": "adafruit_magtag_29gray",
+ "inherits": "default"
+ },
+ {
+ "name": "adafruit_metro_esp32s2",
+ "inherits": "default"
+ },
+ {
+ "name": "apard32690",
+ "inherits": "default"
+ },
+ {
+ "name": "arduino_nano33_ble",
+ "inherits": "default"
+ },
+ {
+ "name": "atsamd21_xpro",
+ "inherits": "default"
+ },
+ {
+ "name": "atsaml21_xpro",
+ "inherits": "default"
+ },
+ {
+ "name": "b_g474e_dpow1",
+ "inherits": "default"
+ },
+ {
+ "name": "b_u585i_iot2a",
+ "inherits": "default"
+ },
+ {
+ "name": "ch32v103r_r1_1v0",
+ "inherits": "default"
+ },
+ {
+ "name": "ch32v203c_r0_1v0",
+ "inherits": "default"
+ },
+ {
+ "name": "ch32v203g_r0_1v0",
+ "inherits": "default"
+ },
+ {
+ "name": "ch32v307v_r1_1v0",
+ "inherits": "default"
+ },
+ {
+ "name": "circuitplayground_bluefruit",
+ "inherits": "default"
+ },
+ {
+ "name": "circuitplayground_express",
+ "inherits": "default"
+ },
+ {
+ "name": "curiosity_nano",
+ "inherits": "default"
+ },
+ {
+ "name": "cynthion_d11",
+ "inherits": "default"
+ },
+ {
+ "name": "cynthion_d21",
+ "inherits": "default"
+ },
+ {
+ "name": "d5035_01",
+ "inherits": "default"
+ },
+ {
+ "name": "da14695_dk_usb",
+ "inherits": "default"
+ },
+ {
+ "name": "da1469x_dk_pro",
+ "inherits": "default"
+ },
+ {
+ "name": "daisyseed",
+ "inherits": "default"
+ },
+ {
+ "name": "double_m33_express",
+ "inherits": "default"
+ },
+ {
+ "name": "ea4088_quickstart",
+ "inherits": "default"
+ },
+ {
+ "name": "ea4357",
+ "inherits": "default"
+ },
+ {
+ "name": "ek_tm4c123gxl",
+ "inherits": "default"
+ },
+ {
+ "name": "espressif_addax_1",
+ "inherits": "default"
+ },
+ {
+ "name": "espressif_c3_devkitc",
+ "inherits": "default"
+ },
+ {
+ "name": "espressif_c6_devkitc",
+ "inherits": "default"
+ },
+ {
+ "name": "espressif_kaluga_1",
+ "inherits": "default"
+ },
+ {
+ "name": "espressif_p4_function_ev",
+ "inherits": "default"
+ },
+ {
+ "name": "espressif_s2_devkitc",
+ "inherits": "default"
+ },
+ {
+ "name": "espressif_s3_devkitc",
+ "inherits": "default"
+ },
+ {
+ "name": "espressif_s3_devkitm",
+ "inherits": "default"
+ },
+ {
+ "name": "espressif_saola_1",
+ "inherits": "default"
+ },
+ {
+ "name": "f1c100s",
+ "inherits": "default"
+ },
+ {
+ "name": "feather_m0_express",
+ "inherits": "default"
+ },
+ {
+ "name": "feather_m4_express",
+ "inherits": "default"
+ },
+ {
+ "name": "feather_nrf52840_express",
+ "inherits": "default"
+ },
+ {
+ "name": "feather_nrf52840_sense",
+ "inherits": "default"
+ },
+ {
+ "name": "feather_rp2040_max3421",
+ "inherits": "default"
+ },
+ {
+ "name": "feather_stm32f405",
+ "inherits": "default"
+ },
+ {
+ "name": "fomu",
+ "inherits": "default"
+ },
+ {
+ "name": "frdm_k32l2a4s",
+ "inherits": "default"
+ },
+ {
+ "name": "frdm_k32l2b",
+ "inherits": "default"
+ },
+ {
+ "name": "frdm_k64f",
+ "inherits": "default"
+ },
+ {
+ "name": "frdm_kl25z",
+ "inherits": "default"
+ },
+ {
+ "name": "frdm_mcxa153",
+ "inherits": "default"
+ },
+ {
+ "name": "frdm_mcxn947",
+ "inherits": "default"
+ },
+ {
+ "name": "itsybitsy_m0",
+ "inherits": "default"
+ },
+ {
+ "name": "itsybitsy_m4",
+ "inherits": "default"
+ },
+ {
+ "name": "itsybitsy_nrf52840",
+ "inherits": "default"
+ },
+ {
+ "name": "kuiic",
+ "inherits": "default"
+ },
+ {
+ "name": "lpcxpresso11u37",
+ "inherits": "default"
+ },
+ {
+ "name": "lpcxpresso11u68",
+ "inherits": "default"
+ },
+ {
+ "name": "lpcxpresso1347",
+ "inherits": "default"
+ },
+ {
+ "name": "lpcxpresso1549",
+ "inherits": "default"
+ },
+ {
+ "name": "lpcxpresso1769",
+ "inherits": "default"
+ },
+ {
+ "name": "lpcxpresso18s37",
+ "inherits": "default"
+ },
+ {
+ "name": "lpcxpresso43s67",
+ "inherits": "default"
+ },
+ {
+ "name": "lpcxpresso51u68",
+ "inherits": "default"
+ },
+ {
+ "name": "lpcxpresso54114",
+ "inherits": "default"
+ },
+ {
+ "name": "lpcxpresso54608",
+ "inherits": "default"
+ },
+ {
+ "name": "lpcxpresso54628",
+ "inherits": "default"
+ },
+ {
+ "name": "lpcxpresso55s28",
+ "inherits": "default"
+ },
+ {
+ "name": "lpcxpresso55s69",
+ "inherits": "default"
+ },
+ {
+ "name": "max32650evkit",
+ "inherits": "default"
+ },
+ {
+ "name": "max32650fthr",
+ "inherits": "default"
+ },
+ {
+ "name": "max32651evkit",
+ "inherits": "default"
+ },
+ {
+ "name": "max32666evkit",
+ "inherits": "default"
+ },
+ {
+ "name": "max32666fthr",
+ "inherits": "default"
+ },
+ {
+ "name": "max32690evkit",
+ "inherits": "default"
+ },
+ {
+ "name": "max78002evkit",
+ "inherits": "default"
+ },
+ {
+ "name": "mbed1768",
+ "inherits": "default"
+ },
+ {
+ "name": "mcb1800",
+ "inherits": "default"
+ },
+ {
+ "name": "mcu_link",
+ "inherits": "default"
+ },
+ {
+ "name": "mcxn947brk",
+ "inherits": "default"
+ },
+ {
+ "name": "metro_m0_express",
+ "inherits": "default"
+ },
+ {
+ "name": "metro_m4_express",
+ "inherits": "default"
+ },
+ {
+ "name": "metro_m7_1011",
+ "inherits": "default"
+ },
+ {
+ "name": "metro_m7_1011_sd",
+ "inherits": "default"
+ },
+ {
+ "name": "mimxrt1010_evk",
+ "inherits": "default"
+ },
+ {
+ "name": "mimxrt1015_evk",
+ "inherits": "default"
+ },
+ {
+ "name": "mimxrt1020_evk",
+ "inherits": "default"
+ },
+ {
+ "name": "mimxrt1024_evk",
+ "inherits": "default"
+ },
+ {
+ "name": "mimxrt1050_evkb",
+ "inherits": "default"
+ },
+ {
+ "name": "mimxrt1060_evk",
+ "inherits": "default"
+ },
+ {
+ "name": "mimxrt1064_evk",
+ "inherits": "default"
+ },
+ {
+ "name": "mimxrt1170_evkb",
+ "inherits": "default"
+ },
+ {
+ "name": "mm32f327x_mb39",
+ "inherits": "default"
+ },
+ {
+ "name": "mm32f327x_pitaya_lite",
+ "inherits": "default"
+ },
+ {
+ "name": "msp_exp430f5529lp",
+ "inherits": "default"
+ },
+ {
+ "name": "msp_exp432e401y",
+ "inherits": "default"
+ },
+ {
+ "name": "nanoch32v203",
+ "inherits": "default"
+ },
+ {
+ "name": "pca10056",
+ "inherits": "default"
+ },
+ {
+ "name": "pca10059",
+ "inherits": "default"
+ },
+ {
+ "name": "pca10095",
+ "inherits": "default"
+ },
+ {
+ "name": "pca10100",
+ "inherits": "default"
+ },
+ {
+ "name": "pico_sdk",
+ "inherits": "default"
+ },
+ {
+ "name": "portenta_c33",
+ "inherits": "default"
+ },
+ {
+ "name": "pybadge",
+ "inherits": "default"
+ },
+ {
+ "name": "pyboardv11",
+ "inherits": "default"
+ },
+ {
+ "name": "pyportal",
+ "inherits": "default"
+ },
+ {
+ "name": "qtpy",
+ "inherits": "default"
+ },
+ {
+ "name": "ra2a1_ek",
+ "inherits": "default"
+ },
+ {
+ "name": "ra4m1_ek",
+ "inherits": "default"
+ },
+ {
+ "name": "ra4m3_ek",
+ "inherits": "default"
+ },
+ {
+ "name": "ra6m1_ek",
+ "inherits": "default"
+ },
+ {
+ "name": "ra6m5_ek",
+ "inherits": "default"
+ },
+ {
+ "name": "ra8m1_ek",
+ "inherits": "default"
+ },
+ {
+ "name": "raspberry_pi_pico",
+ "inherits": "default"
+ },
+ {
+ "name": "raspberry_pi_pico2",
+ "inherits": "default"
+ },
+ {
+ "name": "raspberrypi_cm4",
+ "inherits": "default"
+ },
+ {
+ "name": "raspberrypi_zero",
+ "inherits": "default"
+ },
+ {
+ "name": "raspberrypi_zero2",
+ "inherits": "default"
+ },
+ {
+ "name": "samd11_xplained",
+ "inherits": "default"
+ },
+ {
+ "name": "same54_xplained",
+ "inherits": "default"
+ },
+ {
+ "name": "samg55_xplained",
+ "inherits": "default"
+ },
+ {
+ "name": "saml22_feather",
+ "inherits": "default"
+ },
+ {
+ "name": "seeeduino_xiao",
+ "inherits": "default"
+ },
+ {
+ "name": "sensorwatch_m0",
+ "inherits": "default"
+ },
+ {
+ "name": "sipeed_longan_nano",
+ "inherits": "default"
+ },
+ {
+ "name": "sparkfun_samd21_mini_usb",
+ "inherits": "default"
+ },
+ {
+ "name": "stlinkv3mini",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32c071nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f070rbnucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f072disco",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f072eval",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f103_bluepill",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f103_mini_2",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f103ze_iar",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f207nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f303disco",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f401blackpill",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f407blackvet",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f407disco",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f411blackpill",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f411disco",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f412disco",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f412nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f439nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f723disco",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f746disco",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f746nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f767nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32f769disco",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32g0b1nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32g474nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32g491nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32h503nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32h563nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32h573i_dk",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32h723nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32h743eval",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32h743nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32h745disco",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32h750_weact",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32h750bdk",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32h7s3nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32l052dap52",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32l0538disco",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32l412nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32l476disco",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32l4p5nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32l4r5nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32u545nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32u575eval",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32u575nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32u5a5nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "stm32wb55nucleo",
+ "inherits": "default"
+ },
+ {
+ "name": "teensy_35",
+ "inherits": "default"
+ },
+ {
+ "name": "teensy_40",
+ "inherits": "default"
+ },
+ {
+ "name": "teensy_41",
+ "inherits": "default"
+ },
+ {
+ "name": "trinket_m0",
+ "inherits": "default"
+ },
+ {
+ "name": "uno_r4",
+ "inherits": "default"
+ },
+ {
+ "name": "waveshare_openh743i",
+ "inherits": "default"
+ },
+ {
+ "name": "xmc4500_relax",
+ "inherits": "default"
+ },
+ {
+ "name": "xmc4700_relax",
+ "inherits": "default"
+ }
+ ],
+ "buildPresets": [
+ {
+ "name": "adafruit_clue",
+ "description": "Build preset for the adafruit_clue board",
+ "configurePreset": "adafruit_clue"
+ },
+ {
+ "name": "adafruit_feather_esp32_v2",
+ "description": "Build preset for the adafruit_feather_esp32_v2 board",
+ "configurePreset": "adafruit_feather_esp32_v2"
+ },
+ {
+ "name": "adafruit_feather_esp32s2",
+ "description": "Build preset for the adafruit_feather_esp32s2 board",
+ "configurePreset": "adafruit_feather_esp32s2"
+ },
+ {
+ "name": "adafruit_feather_esp32s3",
+ "description": "Build preset for the adafruit_feather_esp32s3 board",
+ "configurePreset": "adafruit_feather_esp32s3"
+ },
+ {
+ "name": "adafruit_magtag_29gray",
+ "description": "Build preset for the adafruit_magtag_29gray board",
+ "configurePreset": "adafruit_magtag_29gray"
+ },
+ {
+ "name": "adafruit_metro_esp32s2",
+ "description": "Build preset for the adafruit_metro_esp32s2 board",
+ "configurePreset": "adafruit_metro_esp32s2"
+ },
+ {
+ "name": "apard32690",
+ "description": "Build preset for the apard32690 board",
+ "configurePreset": "apard32690"
+ },
+ {
+ "name": "arduino_nano33_ble",
+ "description": "Build preset for the arduino_nano33_ble board",
+ "configurePreset": "arduino_nano33_ble"
+ },
+ {
+ "name": "atsamd21_xpro",
+ "description": "Build preset for the atsamd21_xpro board",
+ "configurePreset": "atsamd21_xpro"
+ },
+ {
+ "name": "atsaml21_xpro",
+ "description": "Build preset for the atsaml21_xpro board",
+ "configurePreset": "atsaml21_xpro"
+ },
+ {
+ "name": "b_g474e_dpow1",
+ "description": "Build preset for the b_g474e_dpow1 board",
+ "configurePreset": "b_g474e_dpow1"
+ },
+ {
+ "name": "b_u585i_iot2a",
+ "description": "Build preset for the b_u585i_iot2a board",
+ "configurePreset": "b_u585i_iot2a"
+ },
+ {
+ "name": "ch32v103r_r1_1v0",
+ "description": "Build preset for the ch32v103r_r1_1v0 board",
+ "configurePreset": "ch32v103r_r1_1v0"
+ },
+ {
+ "name": "ch32v203c_r0_1v0",
+ "description": "Build preset for the ch32v203c_r0_1v0 board",
+ "configurePreset": "ch32v203c_r0_1v0"
+ },
+ {
+ "name": "ch32v203g_r0_1v0",
+ "description": "Build preset for the ch32v203g_r0_1v0 board",
+ "configurePreset": "ch32v203g_r0_1v0"
+ },
+ {
+ "name": "ch32v307v_r1_1v0",
+ "description": "Build preset for the ch32v307v_r1_1v0 board",
+ "configurePreset": "ch32v307v_r1_1v0"
+ },
+ {
+ "name": "circuitplayground_bluefruit",
+ "description": "Build preset for the circuitplayground_bluefruit board",
+ "configurePreset": "circuitplayground_bluefruit"
+ },
+ {
+ "name": "circuitplayground_express",
+ "description": "Build preset for the circuitplayground_express board",
+ "configurePreset": "circuitplayground_express"
+ },
+ {
+ "name": "curiosity_nano",
+ "description": "Build preset for the curiosity_nano board",
+ "configurePreset": "curiosity_nano"
+ },
+ {
+ "name": "cynthion_d11",
+ "description": "Build preset for the cynthion_d11 board",
+ "configurePreset": "cynthion_d11"
+ },
+ {
+ "name": "cynthion_d21",
+ "description": "Build preset for the cynthion_d21 board",
+ "configurePreset": "cynthion_d21"
+ },
+ {
+ "name": "d5035_01",
+ "description": "Build preset for the d5035_01 board",
+ "configurePreset": "d5035_01"
+ },
+ {
+ "name": "da14695_dk_usb",
+ "description": "Build preset for the da14695_dk_usb board",
+ "configurePreset": "da14695_dk_usb"
+ },
+ {
+ "name": "da1469x_dk_pro",
+ "description": "Build preset for the da1469x_dk_pro board",
+ "configurePreset": "da1469x_dk_pro"
+ },
+ {
+ "name": "daisyseed",
+ "description": "Build preset for the daisyseed board",
+ "configurePreset": "daisyseed"
+ },
+ {
+ "name": "double_m33_express",
+ "description": "Build preset for the double_m33_express board",
+ "configurePreset": "double_m33_express"
+ },
+ {
+ "name": "ea4088_quickstart",
+ "description": "Build preset for the ea4088_quickstart board",
+ "configurePreset": "ea4088_quickstart"
+ },
+ {
+ "name": "ea4357",
+ "description": "Build preset for the ea4357 board",
+ "configurePreset": "ea4357"
+ },
+ {
+ "name": "ek_tm4c123gxl",
+ "description": "Build preset for the ek_tm4c123gxl board",
+ "configurePreset": "ek_tm4c123gxl"
+ },
+ {
+ "name": "espressif_addax_1",
+ "description": "Build preset for the espressif_addax_1 board",
+ "configurePreset": "espressif_addax_1"
+ },
+ {
+ "name": "espressif_c3_devkitc",
+ "description": "Build preset for the espressif_c3_devkitc board",
+ "configurePreset": "espressif_c3_devkitc"
+ },
+ {
+ "name": "espressif_c6_devkitc",
+ "description": "Build preset for the espressif_c6_devkitc board",
+ "configurePreset": "espressif_c6_devkitc"
+ },
+ {
+ "name": "espressif_kaluga_1",
+ "description": "Build preset for the espressif_kaluga_1 board",
+ "configurePreset": "espressif_kaluga_1"
+ },
+ {
+ "name": "espressif_p4_function_ev",
+ "description": "Build preset for the espressif_p4_function_ev board",
+ "configurePreset": "espressif_p4_function_ev"
+ },
+ {
+ "name": "espressif_s2_devkitc",
+ "description": "Build preset for the espressif_s2_devkitc board",
+ "configurePreset": "espressif_s2_devkitc"
+ },
+ {
+ "name": "espressif_s3_devkitc",
+ "description": "Build preset for the espressif_s3_devkitc board",
+ "configurePreset": "espressif_s3_devkitc"
+ },
+ {
+ "name": "espressif_s3_devkitm",
+ "description": "Build preset for the espressif_s3_devkitm board",
+ "configurePreset": "espressif_s3_devkitm"
+ },
+ {
+ "name": "espressif_saola_1",
+ "description": "Build preset for the espressif_saola_1 board",
+ "configurePreset": "espressif_saola_1"
+ },
+ {
+ "name": "f1c100s",
+ "description": "Build preset for the f1c100s board",
+ "configurePreset": "f1c100s"
+ },
+ {
+ "name": "feather_m0_express",
+ "description": "Build preset for the feather_m0_express board",
+ "configurePreset": "feather_m0_express"
+ },
+ {
+ "name": "feather_m4_express",
+ "description": "Build preset for the feather_m4_express board",
+ "configurePreset": "feather_m4_express"
+ },
+ {
+ "name": "feather_nrf52840_express",
+ "description": "Build preset for the feather_nrf52840_express board",
+ "configurePreset": "feather_nrf52840_express"
+ },
+ {
+ "name": "feather_nrf52840_sense",
+ "description": "Build preset for the feather_nrf52840_sense board",
+ "configurePreset": "feather_nrf52840_sense"
+ },
+ {
+ "name": "feather_rp2040_max3421",
+ "description": "Build preset for the feather_rp2040_max3421 board",
+ "configurePreset": "feather_rp2040_max3421"
+ },
+ {
+ "name": "feather_stm32f405",
+ "description": "Build preset for the feather_stm32f405 board",
+ "configurePreset": "feather_stm32f405"
+ },
+ {
+ "name": "fomu",
+ "description": "Build preset for the fomu board",
+ "configurePreset": "fomu"
+ },
+ {
+ "name": "frdm_k32l2a4s",
+ "description": "Build preset for the frdm_k32l2a4s board",
+ "configurePreset": "frdm_k32l2a4s"
+ },
+ {
+ "name": "frdm_k32l2b",
+ "description": "Build preset for the frdm_k32l2b board",
+ "configurePreset": "frdm_k32l2b"
+ },
+ {
+ "name": "frdm_k64f",
+ "description": "Build preset for the frdm_k64f board",
+ "configurePreset": "frdm_k64f"
+ },
+ {
+ "name": "frdm_kl25z",
+ "description": "Build preset for the frdm_kl25z board",
+ "configurePreset": "frdm_kl25z"
+ },
+ {
+ "name": "frdm_mcxa153",
+ "description": "Build preset for the frdm_mcxa153 board",
+ "configurePreset": "frdm_mcxa153"
+ },
+ {
+ "name": "frdm_mcxn947",
+ "description": "Build preset for the frdm_mcxn947 board",
+ "configurePreset": "frdm_mcxn947"
+ },
+ {
+ "name": "itsybitsy_m0",
+ "description": "Build preset for the itsybitsy_m0 board",
+ "configurePreset": "itsybitsy_m0"
+ },
+ {
+ "name": "itsybitsy_m4",
+ "description": "Build preset for the itsybitsy_m4 board",
+ "configurePreset": "itsybitsy_m4"
+ },
+ {
+ "name": "itsybitsy_nrf52840",
+ "description": "Build preset for the itsybitsy_nrf52840 board",
+ "configurePreset": "itsybitsy_nrf52840"
+ },
+ {
+ "name": "kuiic",
+ "description": "Build preset for the kuiic board",
+ "configurePreset": "kuiic"
+ },
+ {
+ "name": "lpcxpresso11u37",
+ "description": "Build preset for the lpcxpresso11u37 board",
+ "configurePreset": "lpcxpresso11u37"
+ },
+ {
+ "name": "lpcxpresso11u68",
+ "description": "Build preset for the lpcxpresso11u68 board",
+ "configurePreset": "lpcxpresso11u68"
+ },
+ {
+ "name": "lpcxpresso1347",
+ "description": "Build preset for the lpcxpresso1347 board",
+ "configurePreset": "lpcxpresso1347"
+ },
+ {
+ "name": "lpcxpresso1549",
+ "description": "Build preset for the lpcxpresso1549 board",
+ "configurePreset": "lpcxpresso1549"
+ },
+ {
+ "name": "lpcxpresso1769",
+ "description": "Build preset for the lpcxpresso1769 board",
+ "configurePreset": "lpcxpresso1769"
+ },
+ {
+ "name": "lpcxpresso18s37",
+ "description": "Build preset for the lpcxpresso18s37 board",
+ "configurePreset": "lpcxpresso18s37"
+ },
+ {
+ "name": "lpcxpresso43s67",
+ "description": "Build preset for the lpcxpresso43s67 board",
+ "configurePreset": "lpcxpresso43s67"
+ },
+ {
+ "name": "lpcxpresso51u68",
+ "description": "Build preset for the lpcxpresso51u68 board",
+ "configurePreset": "lpcxpresso51u68"
+ },
+ {
+ "name": "lpcxpresso54114",
+ "description": "Build preset for the lpcxpresso54114 board",
+ "configurePreset": "lpcxpresso54114"
+ },
+ {
+ "name": "lpcxpresso54608",
+ "description": "Build preset for the lpcxpresso54608 board",
+ "configurePreset": "lpcxpresso54608"
+ },
+ {
+ "name": "lpcxpresso54628",
+ "description": "Build preset for the lpcxpresso54628 board",
+ "configurePreset": "lpcxpresso54628"
+ },
+ {
+ "name": "lpcxpresso55s28",
+ "description": "Build preset for the lpcxpresso55s28 board",
+ "configurePreset": "lpcxpresso55s28"
+ },
+ {
+ "name": "lpcxpresso55s69",
+ "description": "Build preset for the lpcxpresso55s69 board",
+ "configurePreset": "lpcxpresso55s69"
+ },
+ {
+ "name": "max32650evkit",
+ "description": "Build preset for the max32650evkit board",
+ "configurePreset": "max32650evkit"
+ },
+ {
+ "name": "max32650fthr",
+ "description": "Build preset for the max32650fthr board",
+ "configurePreset": "max32650fthr"
+ },
+ {
+ "name": "max32651evkit",
+ "description": "Build preset for the max32651evkit board",
+ "configurePreset": "max32651evkit"
+ },
+ {
+ "name": "max32666evkit",
+ "description": "Build preset for the max32666evkit board",
+ "configurePreset": "max32666evkit"
+ },
+ {
+ "name": "max32666fthr",
+ "description": "Build preset for the max32666fthr board",
+ "configurePreset": "max32666fthr"
+ },
+ {
+ "name": "max32690evkit",
+ "description": "Build preset for the max32690evkit board",
+ "configurePreset": "max32690evkit"
+ },
+ {
+ "name": "max78002evkit",
+ "description": "Build preset for the max78002evkit board",
+ "configurePreset": "max78002evkit"
+ },
+ {
+ "name": "mbed1768",
+ "description": "Build preset for the mbed1768 board",
+ "configurePreset": "mbed1768"
+ },
+ {
+ "name": "mcb1800",
+ "description": "Build preset for the mcb1800 board",
+ "configurePreset": "mcb1800"
+ },
+ {
+ "name": "mcu_link",
+ "description": "Build preset for the mcu_link board",
+ "configurePreset": "mcu_link"
+ },
+ {
+ "name": "mcxn947brk",
+ "description": "Build preset for the mcxn947brk board",
+ "configurePreset": "mcxn947brk"
+ },
+ {
+ "name": "metro_m0_express",
+ "description": "Build preset for the metro_m0_express board",
+ "configurePreset": "metro_m0_express"
+ },
+ {
+ "name": "metro_m4_express",
+ "description": "Build preset for the metro_m4_express board",
+ "configurePreset": "metro_m4_express"
+ },
+ {
+ "name": "metro_m7_1011",
+ "description": "Build preset for the metro_m7_1011 board",
+ "configurePreset": "metro_m7_1011"
+ },
+ {
+ "name": "metro_m7_1011_sd",
+ "description": "Build preset for the metro_m7_1011_sd board",
+ "configurePreset": "metro_m7_1011_sd"
+ },
+ {
+ "name": "mimxrt1010_evk",
+ "description": "Build preset for the mimxrt1010_evk board",
+ "configurePreset": "mimxrt1010_evk"
+ },
+ {
+ "name": "mimxrt1015_evk",
+ "description": "Build preset for the mimxrt1015_evk board",
+ "configurePreset": "mimxrt1015_evk"
+ },
+ {
+ "name": "mimxrt1020_evk",
+ "description": "Build preset for the mimxrt1020_evk board",
+ "configurePreset": "mimxrt1020_evk"
+ },
+ {
+ "name": "mimxrt1024_evk",
+ "description": "Build preset for the mimxrt1024_evk board",
+ "configurePreset": "mimxrt1024_evk"
+ },
+ {
+ "name": "mimxrt1050_evkb",
+ "description": "Build preset for the mimxrt1050_evkb board",
+ "configurePreset": "mimxrt1050_evkb"
+ },
+ {
+ "name": "mimxrt1060_evk",
+ "description": "Build preset for the mimxrt1060_evk board",
+ "configurePreset": "mimxrt1060_evk"
+ },
+ {
+ "name": "mimxrt1064_evk",
+ "description": "Build preset for the mimxrt1064_evk board",
+ "configurePreset": "mimxrt1064_evk"
+ },
+ {
+ "name": "mimxrt1170_evkb",
+ "description": "Build preset for the mimxrt1170_evkb board",
+ "configurePreset": "mimxrt1170_evkb"
+ },
+ {
+ "name": "mm32f327x_mb39",
+ "description": "Build preset for the mm32f327x_mb39 board",
+ "configurePreset": "mm32f327x_mb39"
+ },
+ {
+ "name": "mm32f327x_pitaya_lite",
+ "description": "Build preset for the mm32f327x_pitaya_lite board",
+ "configurePreset": "mm32f327x_pitaya_lite"
+ },
+ {
+ "name": "msp_exp430f5529lp",
+ "description": "Build preset for the msp_exp430f5529lp board",
+ "configurePreset": "msp_exp430f5529lp"
+ },
+ {
+ "name": "msp_exp432e401y",
+ "description": "Build preset for the msp_exp432e401y board",
+ "configurePreset": "msp_exp432e401y"
+ },
+ {
+ "name": "nanoch32v203",
+ "description": "Build preset for the nanoch32v203 board",
+ "configurePreset": "nanoch32v203"
+ },
+ {
+ "name": "pca10056",
+ "description": "Build preset for the pca10056 board",
+ "configurePreset": "pca10056"
+ },
+ {
+ "name": "pca10059",
+ "description": "Build preset for the pca10059 board",
+ "configurePreset": "pca10059"
+ },
+ {
+ "name": "pca10095",
+ "description": "Build preset for the pca10095 board",
+ "configurePreset": "pca10095"
+ },
+ {
+ "name": "pca10100",
+ "description": "Build preset for the pca10100 board",
+ "configurePreset": "pca10100"
+ },
+ {
+ "name": "pico_sdk",
+ "description": "Build preset for the pico_sdk board",
+ "configurePreset": "pico_sdk"
+ },
+ {
+ "name": "portenta_c33",
+ "description": "Build preset for the portenta_c33 board",
+ "configurePreset": "portenta_c33"
+ },
+ {
+ "name": "pybadge",
+ "description": "Build preset for the pybadge board",
+ "configurePreset": "pybadge"
+ },
+ {
+ "name": "pyboardv11",
+ "description": "Build preset for the pyboardv11 board",
+ "configurePreset": "pyboardv11"
+ },
+ {
+ "name": "pyportal",
+ "description": "Build preset for the pyportal board",
+ "configurePreset": "pyportal"
+ },
+ {
+ "name": "qtpy",
+ "description": "Build preset for the qtpy board",
+ "configurePreset": "qtpy"
+ },
+ {
+ "name": "ra2a1_ek",
+ "description": "Build preset for the ra2a1_ek board",
+ "configurePreset": "ra2a1_ek"
+ },
+ {
+ "name": "ra4m1_ek",
+ "description": "Build preset for the ra4m1_ek board",
+ "configurePreset": "ra4m1_ek"
+ },
+ {
+ "name": "ra4m3_ek",
+ "description": "Build preset for the ra4m3_ek board",
+ "configurePreset": "ra4m3_ek"
+ },
+ {
+ "name": "ra6m1_ek",
+ "description": "Build preset for the ra6m1_ek board",
+ "configurePreset": "ra6m1_ek"
+ },
+ {
+ "name": "ra6m5_ek",
+ "description": "Build preset for the ra6m5_ek board",
+ "configurePreset": "ra6m5_ek"
+ },
+ {
+ "name": "ra8m1_ek",
+ "description": "Build preset for the ra8m1_ek board",
+ "configurePreset": "ra8m1_ek"
+ },
+ {
+ "name": "raspberry_pi_pico",
+ "description": "Build preset for the raspberry_pi_pico board",
+ "configurePreset": "raspberry_pi_pico"
+ },
+ {
+ "name": "raspberry_pi_pico2",
+ "description": "Build preset for the raspberry_pi_pico2 board",
+ "configurePreset": "raspberry_pi_pico2"
+ },
+ {
+ "name": "raspberrypi_cm4",
+ "description": "Build preset for the raspberrypi_cm4 board",
+ "configurePreset": "raspberrypi_cm4"
+ },
+ {
+ "name": "raspberrypi_zero",
+ "description": "Build preset for the raspberrypi_zero board",
+ "configurePreset": "raspberrypi_zero"
+ },
+ {
+ "name": "raspberrypi_zero2",
+ "description": "Build preset for the raspberrypi_zero2 board",
+ "configurePreset": "raspberrypi_zero2"
+ },
+ {
+ "name": "samd11_xplained",
+ "description": "Build preset for the samd11_xplained board",
+ "configurePreset": "samd11_xplained"
+ },
+ {
+ "name": "same54_xplained",
+ "description": "Build preset for the same54_xplained board",
+ "configurePreset": "same54_xplained"
+ },
+ {
+ "name": "samg55_xplained",
+ "description": "Build preset for the samg55_xplained board",
+ "configurePreset": "samg55_xplained"
+ },
+ {
+ "name": "saml22_feather",
+ "description": "Build preset for the saml22_feather board",
+ "configurePreset": "saml22_feather"
+ },
+ {
+ "name": "seeeduino_xiao",
+ "description": "Build preset for the seeeduino_xiao board",
+ "configurePreset": "seeeduino_xiao"
+ },
+ {
+ "name": "sensorwatch_m0",
+ "description": "Build preset for the sensorwatch_m0 board",
+ "configurePreset": "sensorwatch_m0"
+ },
+ {
+ "name": "sipeed_longan_nano",
+ "description": "Build preset for the sipeed_longan_nano board",
+ "configurePreset": "sipeed_longan_nano"
+ },
+ {
+ "name": "sparkfun_samd21_mini_usb",
+ "description": "Build preset for the sparkfun_samd21_mini_usb board",
+ "configurePreset": "sparkfun_samd21_mini_usb"
+ },
+ {
+ "name": "stlinkv3mini",
+ "description": "Build preset for the stlinkv3mini board",
+ "configurePreset": "stlinkv3mini"
+ },
+ {
+ "name": "stm32c071nucleo",
+ "description": "Build preset for the stm32c071nucleo board",
+ "configurePreset": "stm32c071nucleo"
+ },
+ {
+ "name": "stm32f070rbnucleo",
+ "description": "Build preset for the stm32f070rbnucleo board",
+ "configurePreset": "stm32f070rbnucleo"
+ },
+ {
+ "name": "stm32f072disco",
+ "description": "Build preset for the stm32f072disco board",
+ "configurePreset": "stm32f072disco"
+ },
+ {
+ "name": "stm32f072eval",
+ "description": "Build preset for the stm32f072eval board",
+ "configurePreset": "stm32f072eval"
+ },
+ {
+ "name": "stm32f103_bluepill",
+ "description": "Build preset for the stm32f103_bluepill board",
+ "configurePreset": "stm32f103_bluepill"
+ },
+ {
+ "name": "stm32f103_mini_2",
+ "description": "Build preset for the stm32f103_mini_2 board",
+ "configurePreset": "stm32f103_mini_2"
+ },
+ {
+ "name": "stm32f103ze_iar",
+ "description": "Build preset for the stm32f103ze_iar board",
+ "configurePreset": "stm32f103ze_iar"
+ },
+ {
+ "name": "stm32f207nucleo",
+ "description": "Build preset for the stm32f207nucleo board",
+ "configurePreset": "stm32f207nucleo"
+ },
+ {
+ "name": "stm32f303disco",
+ "description": "Build preset for the stm32f303disco board",
+ "configurePreset": "stm32f303disco"
+ },
+ {
+ "name": "stm32f401blackpill",
+ "description": "Build preset for the stm32f401blackpill board",
+ "configurePreset": "stm32f401blackpill"
+ },
+ {
+ "name": "stm32f407blackvet",
+ "description": "Build preset for the stm32f407blackvet board",
+ "configurePreset": "stm32f407blackvet"
+ },
+ {
+ "name": "stm32f407disco",
+ "description": "Build preset for the stm32f407disco board",
+ "configurePreset": "stm32f407disco"
+ },
+ {
+ "name": "stm32f411blackpill",
+ "description": "Build preset for the stm32f411blackpill board",
+ "configurePreset": "stm32f411blackpill"
+ },
+ {
+ "name": "stm32f411disco",
+ "description": "Build preset for the stm32f411disco board",
+ "configurePreset": "stm32f411disco"
+ },
+ {
+ "name": "stm32f412disco",
+ "description": "Build preset for the stm32f412disco board",
+ "configurePreset": "stm32f412disco"
+ },
+ {
+ "name": "stm32f412nucleo",
+ "description": "Build preset for the stm32f412nucleo board",
+ "configurePreset": "stm32f412nucleo"
+ },
+ {
+ "name": "stm32f439nucleo",
+ "description": "Build preset for the stm32f439nucleo board",
+ "configurePreset": "stm32f439nucleo"
+ },
+ {
+ "name": "stm32f723disco",
+ "description": "Build preset for the stm32f723disco board",
+ "configurePreset": "stm32f723disco"
+ },
+ {
+ "name": "stm32f746disco",
+ "description": "Build preset for the stm32f746disco board",
+ "configurePreset": "stm32f746disco"
+ },
+ {
+ "name": "stm32f746nucleo",
+ "description": "Build preset for the stm32f746nucleo board",
+ "configurePreset": "stm32f746nucleo"
+ },
+ {
+ "name": "stm32f767nucleo",
+ "description": "Build preset for the stm32f767nucleo board",
+ "configurePreset": "stm32f767nucleo"
+ },
+ {
+ "name": "stm32f769disco",
+ "description": "Build preset for the stm32f769disco board",
+ "configurePreset": "stm32f769disco"
+ },
+ {
+ "name": "stm32g0b1nucleo",
+ "description": "Build preset for the stm32g0b1nucleo board",
+ "configurePreset": "stm32g0b1nucleo"
+ },
+ {
+ "name": "stm32g474nucleo",
+ "description": "Build preset for the stm32g474nucleo board",
+ "configurePreset": "stm32g474nucleo"
+ },
+ {
+ "name": "stm32g491nucleo",
+ "description": "Build preset for the stm32g491nucleo board",
+ "configurePreset": "stm32g491nucleo"
+ },
+ {
+ "name": "stm32h503nucleo",
+ "description": "Build preset for the stm32h503nucleo board",
+ "configurePreset": "stm32h503nucleo"
+ },
+ {
+ "name": "stm32h563nucleo",
+ "description": "Build preset for the stm32h563nucleo board",
+ "configurePreset": "stm32h563nucleo"
+ },
+ {
+ "name": "stm32h573i_dk",
+ "description": "Build preset for the stm32h573i_dk board",
+ "configurePreset": "stm32h573i_dk"
+ },
+ {
+ "name": "stm32h723nucleo",
+ "description": "Build preset for the stm32h723nucleo board",
+ "configurePreset": "stm32h723nucleo"
+ },
+ {
+ "name": "stm32h743eval",
+ "description": "Build preset for the stm32h743eval board",
+ "configurePreset": "stm32h743eval"
+ },
+ {
+ "name": "stm32h743nucleo",
+ "description": "Build preset for the stm32h743nucleo board",
+ "configurePreset": "stm32h743nucleo"
+ },
+ {
+ "name": "stm32h745disco",
+ "description": "Build preset for the stm32h745disco board",
+ "configurePreset": "stm32h745disco"
+ },
+ {
+ "name": "stm32h750_weact",
+ "description": "Build preset for the stm32h750_weact board",
+ "configurePreset": "stm32h750_weact"
+ },
+ {
+ "name": "stm32h750bdk",
+ "description": "Build preset for the stm32h750bdk board",
+ "configurePreset": "stm32h750bdk"
+ },
+ {
+ "name": "stm32h7s3nucleo",
+ "description": "Build preset for the stm32h7s3nucleo board",
+ "configurePreset": "stm32h7s3nucleo"
+ },
+ {
+ "name": "stm32l052dap52",
+ "description": "Build preset for the stm32l052dap52 board",
+ "configurePreset": "stm32l052dap52"
+ },
+ {
+ "name": "stm32l0538disco",
+ "description": "Build preset for the stm32l0538disco board",
+ "configurePreset": "stm32l0538disco"
+ },
+ {
+ "name": "stm32l412nucleo",
+ "description": "Build preset for the stm32l412nucleo board",
+ "configurePreset": "stm32l412nucleo"
+ },
+ {
+ "name": "stm32l476disco",
+ "description": "Build preset for the stm32l476disco board",
+ "configurePreset": "stm32l476disco"
+ },
+ {
+ "name": "stm32l4p5nucleo",
+ "description": "Build preset for the stm32l4p5nucleo board",
+ "configurePreset": "stm32l4p5nucleo"
+ },
+ {
+ "name": "stm32l4r5nucleo",
+ "description": "Build preset for the stm32l4r5nucleo board",
+ "configurePreset": "stm32l4r5nucleo"
+ },
+ {
+ "name": "stm32u545nucleo",
+ "description": "Build preset for the stm32u545nucleo board",
+ "configurePreset": "stm32u545nucleo"
+ },
+ {
+ "name": "stm32u575eval",
+ "description": "Build preset for the stm32u575eval board",
+ "configurePreset": "stm32u575eval"
+ },
+ {
+ "name": "stm32u575nucleo",
+ "description": "Build preset for the stm32u575nucleo board",
+ "configurePreset": "stm32u575nucleo"
+ },
+ {
+ "name": "stm32u5a5nucleo",
+ "description": "Build preset for the stm32u5a5nucleo board",
+ "configurePreset": "stm32u5a5nucleo"
+ },
+ {
+ "name": "stm32wb55nucleo",
+ "description": "Build preset for the stm32wb55nucleo board",
+ "configurePreset": "stm32wb55nucleo"
+ },
+ {
+ "name": "teensy_35",
+ "description": "Build preset for the teensy_35 board",
+ "configurePreset": "teensy_35"
+ },
+ {
+ "name": "teensy_40",
+ "description": "Build preset for the teensy_40 board",
+ "configurePreset": "teensy_40"
+ },
+ {
+ "name": "teensy_41",
+ "description": "Build preset for the teensy_41 board",
+ "configurePreset": "teensy_41"
+ },
+ {
+ "name": "trinket_m0",
+ "description": "Build preset for the trinket_m0 board",
+ "configurePreset": "trinket_m0"
+ },
+ {
+ "name": "uno_r4",
+ "description": "Build preset for the uno_r4 board",
+ "configurePreset": "uno_r4"
+ },
+ {
+ "name": "waveshare_openh743i",
+ "description": "Build preset for the waveshare_openh743i board",
+ "configurePreset": "waveshare_openh743i"
+ },
+ {
+ "name": "xmc4500_relax",
+ "description": "Build preset for the xmc4500_relax board",
+ "configurePreset": "xmc4500_relax"
+ },
+ {
+ "name": "xmc4700_relax",
+ "description": "Build preset for the xmc4700_relax board",
+ "configurePreset": "xmc4700_relax"
+ }
+ ],
+ "workflowPresets": [
+ {
+ "name": "adafruit_clue",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "adafruit_clue"
+ },
+ {
+ "type": "build",
+ "name": "adafruit_clue"
+ }
+ ]
+ },
+ {
+ "name": "adafruit_feather_esp32_v2",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "adafruit_feather_esp32_v2"
+ },
+ {
+ "type": "build",
+ "name": "adafruit_feather_esp32_v2"
+ }
+ ]
+ },
+ {
+ "name": "adafruit_feather_esp32s2",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "adafruit_feather_esp32s2"
+ },
+ {
+ "type": "build",
+ "name": "adafruit_feather_esp32s2"
+ }
+ ]
+ },
+ {
+ "name": "adafruit_feather_esp32s3",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "adafruit_feather_esp32s3"
+ },
+ {
+ "type": "build",
+ "name": "adafruit_feather_esp32s3"
+ }
+ ]
+ },
+ {
+ "name": "adafruit_magtag_29gray",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "adafruit_magtag_29gray"
+ },
+ {
+ "type": "build",
+ "name": "adafruit_magtag_29gray"
+ }
+ ]
+ },
+ {
+ "name": "adafruit_metro_esp32s2",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "adafruit_metro_esp32s2"
+ },
+ {
+ "type": "build",
+ "name": "adafruit_metro_esp32s2"
+ }
+ ]
+ },
+ {
+ "name": "apard32690",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "apard32690"
+ },
+ {
+ "type": "build",
+ "name": "apard32690"
+ }
+ ]
+ },
+ {
+ "name": "arduino_nano33_ble",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "arduino_nano33_ble"
+ },
+ {
+ "type": "build",
+ "name": "arduino_nano33_ble"
+ }
+ ]
+ },
+ {
+ "name": "atsamd21_xpro",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "atsamd21_xpro"
+ },
+ {
+ "type": "build",
+ "name": "atsamd21_xpro"
+ }
+ ]
+ },
+ {
+ "name": "atsaml21_xpro",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "atsaml21_xpro"
+ },
+ {
+ "type": "build",
+ "name": "atsaml21_xpro"
+ }
+ ]
+ },
+ {
+ "name": "b_g474e_dpow1",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "b_g474e_dpow1"
+ },
+ {
+ "type": "build",
+ "name": "b_g474e_dpow1"
+ }
+ ]
+ },
+ {
+ "name": "b_u585i_iot2a",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "b_u585i_iot2a"
+ },
+ {
+ "type": "build",
+ "name": "b_u585i_iot2a"
+ }
+ ]
+ },
+ {
+ "name": "ch32v103r_r1_1v0",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "ch32v103r_r1_1v0"
+ },
+ {
+ "type": "build",
+ "name": "ch32v103r_r1_1v0"
+ }
+ ]
+ },
+ {
+ "name": "ch32v203c_r0_1v0",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "ch32v203c_r0_1v0"
+ },
+ {
+ "type": "build",
+ "name": "ch32v203c_r0_1v0"
+ }
+ ]
+ },
+ {
+ "name": "ch32v203g_r0_1v0",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "ch32v203g_r0_1v0"
+ },
+ {
+ "type": "build",
+ "name": "ch32v203g_r0_1v0"
+ }
+ ]
+ },
+ {
+ "name": "ch32v307v_r1_1v0",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "ch32v307v_r1_1v0"
+ },
+ {
+ "type": "build",
+ "name": "ch32v307v_r1_1v0"
+ }
+ ]
+ },
+ {
+ "name": "circuitplayground_bluefruit",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "circuitplayground_bluefruit"
+ },
+ {
+ "type": "build",
+ "name": "circuitplayground_bluefruit"
+ }
+ ]
+ },
+ {
+ "name": "circuitplayground_express",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "circuitplayground_express"
+ },
+ {
+ "type": "build",
+ "name": "circuitplayground_express"
+ }
+ ]
+ },
+ {
+ "name": "curiosity_nano",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "curiosity_nano"
+ },
+ {
+ "type": "build",
+ "name": "curiosity_nano"
+ }
+ ]
+ },
+ {
+ "name": "cynthion_d11",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "cynthion_d11"
+ },
+ {
+ "type": "build",
+ "name": "cynthion_d11"
+ }
+ ]
+ },
+ {
+ "name": "cynthion_d21",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "cynthion_d21"
+ },
+ {
+ "type": "build",
+ "name": "cynthion_d21"
+ }
+ ]
+ },
+ {
+ "name": "d5035_01",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "d5035_01"
+ },
+ {
+ "type": "build",
+ "name": "d5035_01"
+ }
+ ]
+ },
+ {
+ "name": "da14695_dk_usb",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "da14695_dk_usb"
+ },
+ {
+ "type": "build",
+ "name": "da14695_dk_usb"
+ }
+ ]
+ },
+ {
+ "name": "da1469x_dk_pro",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "da1469x_dk_pro"
+ },
+ {
+ "type": "build",
+ "name": "da1469x_dk_pro"
+ }
+ ]
+ },
+ {
+ "name": "daisyseed",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "daisyseed"
+ },
+ {
+ "type": "build",
+ "name": "daisyseed"
+ }
+ ]
+ },
+ {
+ "name": "double_m33_express",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "double_m33_express"
+ },
+ {
+ "type": "build",
+ "name": "double_m33_express"
+ }
+ ]
+ },
+ {
+ "name": "ea4088_quickstart",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "ea4088_quickstart"
+ },
+ {
+ "type": "build",
+ "name": "ea4088_quickstart"
+ }
+ ]
+ },
+ {
+ "name": "ea4357",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "ea4357"
+ },
+ {
+ "type": "build",
+ "name": "ea4357"
+ }
+ ]
+ },
+ {
+ "name": "ek_tm4c123gxl",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "ek_tm4c123gxl"
+ },
+ {
+ "type": "build",
+ "name": "ek_tm4c123gxl"
+ }
+ ]
+ },
+ {
+ "name": "espressif_addax_1",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "espressif_addax_1"
+ },
+ {
+ "type": "build",
+ "name": "espressif_addax_1"
+ }
+ ]
+ },
+ {
+ "name": "espressif_c3_devkitc",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "espressif_c3_devkitc"
+ },
+ {
+ "type": "build",
+ "name": "espressif_c3_devkitc"
+ }
+ ]
+ },
+ {
+ "name": "espressif_c6_devkitc",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "espressif_c6_devkitc"
+ },
+ {
+ "type": "build",
+ "name": "espressif_c6_devkitc"
+ }
+ ]
+ },
+ {
+ "name": "espressif_kaluga_1",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "espressif_kaluga_1"
+ },
+ {
+ "type": "build",
+ "name": "espressif_kaluga_1"
+ }
+ ]
+ },
+ {
+ "name": "espressif_p4_function_ev",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "espressif_p4_function_ev"
+ },
+ {
+ "type": "build",
+ "name": "espressif_p4_function_ev"
+ }
+ ]
+ },
+ {
+ "name": "espressif_s2_devkitc",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "espressif_s2_devkitc"
+ },
+ {
+ "type": "build",
+ "name": "espressif_s2_devkitc"
+ }
+ ]
+ },
+ {
+ "name": "espressif_s3_devkitc",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "espressif_s3_devkitc"
+ },
+ {
+ "type": "build",
+ "name": "espressif_s3_devkitc"
+ }
+ ]
+ },
+ {
+ "name": "espressif_s3_devkitm",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "espressif_s3_devkitm"
+ },
+ {
+ "type": "build",
+ "name": "espressif_s3_devkitm"
+ }
+ ]
+ },
+ {
+ "name": "espressif_saola_1",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "espressif_saola_1"
+ },
+ {
+ "type": "build",
+ "name": "espressif_saola_1"
+ }
+ ]
+ },
+ {
+ "name": "f1c100s",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "f1c100s"
+ },
+ {
+ "type": "build",
+ "name": "f1c100s"
+ }
+ ]
+ },
+ {
+ "name": "feather_m0_express",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "feather_m0_express"
+ },
+ {
+ "type": "build",
+ "name": "feather_m0_express"
+ }
+ ]
+ },
+ {
+ "name": "feather_m4_express",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "feather_m4_express"
+ },
+ {
+ "type": "build",
+ "name": "feather_m4_express"
+ }
+ ]
+ },
+ {
+ "name": "feather_nrf52840_express",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "feather_nrf52840_express"
+ },
+ {
+ "type": "build",
+ "name": "feather_nrf52840_express"
+ }
+ ]
+ },
+ {
+ "name": "feather_nrf52840_sense",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "feather_nrf52840_sense"
+ },
+ {
+ "type": "build",
+ "name": "feather_nrf52840_sense"
+ }
+ ]
+ },
+ {
+ "name": "feather_rp2040_max3421",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "feather_rp2040_max3421"
+ },
+ {
+ "type": "build",
+ "name": "feather_rp2040_max3421"
+ }
+ ]
+ },
+ {
+ "name": "feather_stm32f405",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "feather_stm32f405"
+ },
+ {
+ "type": "build",
+ "name": "feather_stm32f405"
+ }
+ ]
+ },
+ {
+ "name": "fomu",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "fomu"
+ },
+ {
+ "type": "build",
+ "name": "fomu"
+ }
+ ]
+ },
+ {
+ "name": "frdm_k32l2a4s",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "frdm_k32l2a4s"
+ },
+ {
+ "type": "build",
+ "name": "frdm_k32l2a4s"
+ }
+ ]
+ },
+ {
+ "name": "frdm_k32l2b",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "frdm_k32l2b"
+ },
+ {
+ "type": "build",
+ "name": "frdm_k32l2b"
+ }
+ ]
+ },
+ {
+ "name": "frdm_k64f",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "frdm_k64f"
+ },
+ {
+ "type": "build",
+ "name": "frdm_k64f"
+ }
+ ]
+ },
+ {
+ "name": "frdm_kl25z",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "frdm_kl25z"
+ },
+ {
+ "type": "build",
+ "name": "frdm_kl25z"
+ }
+ ]
+ },
+ {
+ "name": "frdm_mcxa153",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "frdm_mcxa153"
+ },
+ {
+ "type": "build",
+ "name": "frdm_mcxa153"
+ }
+ ]
+ },
+ {
+ "name": "frdm_mcxn947",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "frdm_mcxn947"
+ },
+ {
+ "type": "build",
+ "name": "frdm_mcxn947"
+ }
+ ]
+ },
+ {
+ "name": "itsybitsy_m0",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "itsybitsy_m0"
+ },
+ {
+ "type": "build",
+ "name": "itsybitsy_m0"
+ }
+ ]
+ },
+ {
+ "name": "itsybitsy_m4",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "itsybitsy_m4"
+ },
+ {
+ "type": "build",
+ "name": "itsybitsy_m4"
+ }
+ ]
+ },
+ {
+ "name": "itsybitsy_nrf52840",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "itsybitsy_nrf52840"
+ },
+ {
+ "type": "build",
+ "name": "itsybitsy_nrf52840"
+ }
+ ]
+ },
+ {
+ "name": "kuiic",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "kuiic"
+ },
+ {
+ "type": "build",
+ "name": "kuiic"
+ }
+ ]
+ },
+ {
+ "name": "lpcxpresso11u37",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "lpcxpresso11u37"
+ },
+ {
+ "type": "build",
+ "name": "lpcxpresso11u37"
+ }
+ ]
+ },
+ {
+ "name": "lpcxpresso11u68",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "lpcxpresso11u68"
+ },
+ {
+ "type": "build",
+ "name": "lpcxpresso11u68"
+ }
+ ]
+ },
+ {
+ "name": "lpcxpresso1347",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "lpcxpresso1347"
+ },
+ {
+ "type": "build",
+ "name": "lpcxpresso1347"
+ }
+ ]
+ },
+ {
+ "name": "lpcxpresso1549",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "lpcxpresso1549"
+ },
+ {
+ "type": "build",
+ "name": "lpcxpresso1549"
+ }
+ ]
+ },
+ {
+ "name": "lpcxpresso1769",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "lpcxpresso1769"
+ },
+ {
+ "type": "build",
+ "name": "lpcxpresso1769"
+ }
+ ]
+ },
+ {
+ "name": "lpcxpresso18s37",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "lpcxpresso18s37"
+ },
+ {
+ "type": "build",
+ "name": "lpcxpresso18s37"
+ }
+ ]
+ },
+ {
+ "name": "lpcxpresso43s67",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "lpcxpresso43s67"
+ },
+ {
+ "type": "build",
+ "name": "lpcxpresso43s67"
+ }
+ ]
+ },
+ {
+ "name": "lpcxpresso51u68",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "lpcxpresso51u68"
+ },
+ {
+ "type": "build",
+ "name": "lpcxpresso51u68"
+ }
+ ]
+ },
+ {
+ "name": "lpcxpresso54114",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "lpcxpresso54114"
+ },
+ {
+ "type": "build",
+ "name": "lpcxpresso54114"
+ }
+ ]
+ },
+ {
+ "name": "lpcxpresso54608",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "lpcxpresso54608"
+ },
+ {
+ "type": "build",
+ "name": "lpcxpresso54608"
+ }
+ ]
+ },
+ {
+ "name": "lpcxpresso54628",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "lpcxpresso54628"
+ },
+ {
+ "type": "build",
+ "name": "lpcxpresso54628"
+ }
+ ]
+ },
+ {
+ "name": "lpcxpresso55s28",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "lpcxpresso55s28"
+ },
+ {
+ "type": "build",
+ "name": "lpcxpresso55s28"
+ }
+ ]
+ },
+ {
+ "name": "lpcxpresso55s69",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "lpcxpresso55s69"
+ },
+ {
+ "type": "build",
+ "name": "lpcxpresso55s69"
+ }
+ ]
+ },
+ {
+ "name": "max32650evkit",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "max32650evkit"
+ },
+ {
+ "type": "build",
+ "name": "max32650evkit"
+ }
+ ]
+ },
+ {
+ "name": "max32650fthr",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "max32650fthr"
+ },
+ {
+ "type": "build",
+ "name": "max32650fthr"
+ }
+ ]
+ },
+ {
+ "name": "max32651evkit",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "max32651evkit"
+ },
+ {
+ "type": "build",
+ "name": "max32651evkit"
+ }
+ ]
+ },
+ {
+ "name": "max32666evkit",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "max32666evkit"
+ },
+ {
+ "type": "build",
+ "name": "max32666evkit"
+ }
+ ]
+ },
+ {
+ "name": "max32666fthr",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "max32666fthr"
+ },
+ {
+ "type": "build",
+ "name": "max32666fthr"
+ }
+ ]
+ },
+ {
+ "name": "max32690evkit",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "max32690evkit"
+ },
+ {
+ "type": "build",
+ "name": "max32690evkit"
+ }
+ ]
+ },
+ {
+ "name": "max78002evkit",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "max78002evkit"
+ },
+ {
+ "type": "build",
+ "name": "max78002evkit"
+ }
+ ]
+ },
+ {
+ "name": "mbed1768",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "mbed1768"
+ },
+ {
+ "type": "build",
+ "name": "mbed1768"
+ }
+ ]
+ },
+ {
+ "name": "mcb1800",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "mcb1800"
+ },
+ {
+ "type": "build",
+ "name": "mcb1800"
+ }
+ ]
+ },
+ {
+ "name": "mcu_link",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "mcu_link"
+ },
+ {
+ "type": "build",
+ "name": "mcu_link"
+ }
+ ]
+ },
+ {
+ "name": "mcxn947brk",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "mcxn947brk"
+ },
+ {
+ "type": "build",
+ "name": "mcxn947brk"
+ }
+ ]
+ },
+ {
+ "name": "metro_m0_express",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "metro_m0_express"
+ },
+ {
+ "type": "build",
+ "name": "metro_m0_express"
+ }
+ ]
+ },
+ {
+ "name": "metro_m4_express",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "metro_m4_express"
+ },
+ {
+ "type": "build",
+ "name": "metro_m4_express"
+ }
+ ]
+ },
+ {
+ "name": "metro_m7_1011",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "metro_m7_1011"
+ },
+ {
+ "type": "build",
+ "name": "metro_m7_1011"
+ }
+ ]
+ },
+ {
+ "name": "metro_m7_1011_sd",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "metro_m7_1011_sd"
+ },
+ {
+ "type": "build",
+ "name": "metro_m7_1011_sd"
+ }
+ ]
+ },
+ {
+ "name": "mimxrt1010_evk",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "mimxrt1010_evk"
+ },
+ {
+ "type": "build",
+ "name": "mimxrt1010_evk"
+ }
+ ]
+ },
+ {
+ "name": "mimxrt1015_evk",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "mimxrt1015_evk"
+ },
+ {
+ "type": "build",
+ "name": "mimxrt1015_evk"
+ }
+ ]
+ },
+ {
+ "name": "mimxrt1020_evk",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "mimxrt1020_evk"
+ },
+ {
+ "type": "build",
+ "name": "mimxrt1020_evk"
+ }
+ ]
+ },
+ {
+ "name": "mimxrt1024_evk",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "mimxrt1024_evk"
+ },
+ {
+ "type": "build",
+ "name": "mimxrt1024_evk"
+ }
+ ]
+ },
+ {
+ "name": "mimxrt1050_evkb",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "mimxrt1050_evkb"
+ },
+ {
+ "type": "build",
+ "name": "mimxrt1050_evkb"
+ }
+ ]
+ },
+ {
+ "name": "mimxrt1060_evk",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "mimxrt1060_evk"
+ },
+ {
+ "type": "build",
+ "name": "mimxrt1060_evk"
+ }
+ ]
+ },
+ {
+ "name": "mimxrt1064_evk",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "mimxrt1064_evk"
+ },
+ {
+ "type": "build",
+ "name": "mimxrt1064_evk"
+ }
+ ]
+ },
+ {
+ "name": "mimxrt1170_evkb",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "mimxrt1170_evkb"
+ },
+ {
+ "type": "build",
+ "name": "mimxrt1170_evkb"
+ }
+ ]
+ },
+ {
+ "name": "mm32f327x_mb39",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "mm32f327x_mb39"
+ },
+ {
+ "type": "build",
+ "name": "mm32f327x_mb39"
+ }
+ ]
+ },
+ {
+ "name": "mm32f327x_pitaya_lite",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "mm32f327x_pitaya_lite"
+ },
+ {
+ "type": "build",
+ "name": "mm32f327x_pitaya_lite"
+ }
+ ]
+ },
+ {
+ "name": "msp_exp430f5529lp",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "msp_exp430f5529lp"
+ },
+ {
+ "type": "build",
+ "name": "msp_exp430f5529lp"
+ }
+ ]
+ },
+ {
+ "name": "msp_exp432e401y",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "msp_exp432e401y"
+ },
+ {
+ "type": "build",
+ "name": "msp_exp432e401y"
+ }
+ ]
+ },
+ {
+ "name": "nanoch32v203",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "nanoch32v203"
+ },
+ {
+ "type": "build",
+ "name": "nanoch32v203"
+ }
+ ]
+ },
+ {
+ "name": "pca10056",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "pca10056"
+ },
+ {
+ "type": "build",
+ "name": "pca10056"
+ }
+ ]
+ },
+ {
+ "name": "pca10059",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "pca10059"
+ },
+ {
+ "type": "build",
+ "name": "pca10059"
+ }
+ ]
+ },
+ {
+ "name": "pca10095",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "pca10095"
+ },
+ {
+ "type": "build",
+ "name": "pca10095"
+ }
+ ]
+ },
+ {
+ "name": "pca10100",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "pca10100"
+ },
+ {
+ "type": "build",
+ "name": "pca10100"
+ }
+ ]
+ },
+ {
+ "name": "pico_sdk",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "pico_sdk"
+ },
+ {
+ "type": "build",
+ "name": "pico_sdk"
+ }
+ ]
+ },
+ {
+ "name": "portenta_c33",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "portenta_c33"
+ },
+ {
+ "type": "build",
+ "name": "portenta_c33"
+ }
+ ]
+ },
+ {
+ "name": "pybadge",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "pybadge"
+ },
+ {
+ "type": "build",
+ "name": "pybadge"
+ }
+ ]
+ },
+ {
+ "name": "pyboardv11",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "pyboardv11"
+ },
+ {
+ "type": "build",
+ "name": "pyboardv11"
+ }
+ ]
+ },
+ {
+ "name": "pyportal",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "pyportal"
+ },
+ {
+ "type": "build",
+ "name": "pyportal"
+ }
+ ]
+ },
+ {
+ "name": "qtpy",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "qtpy"
+ },
+ {
+ "type": "build",
+ "name": "qtpy"
+ }
+ ]
+ },
+ {
+ "name": "ra2a1_ek",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "ra2a1_ek"
+ },
+ {
+ "type": "build",
+ "name": "ra2a1_ek"
+ }
+ ]
+ },
+ {
+ "name": "ra4m1_ek",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "ra4m1_ek"
+ },
+ {
+ "type": "build",
+ "name": "ra4m1_ek"
+ }
+ ]
+ },
+ {
+ "name": "ra4m3_ek",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "ra4m3_ek"
+ },
+ {
+ "type": "build",
+ "name": "ra4m3_ek"
+ }
+ ]
+ },
+ {
+ "name": "ra6m1_ek",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "ra6m1_ek"
+ },
+ {
+ "type": "build",
+ "name": "ra6m1_ek"
+ }
+ ]
+ },
+ {
+ "name": "ra6m5_ek",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "ra6m5_ek"
+ },
+ {
+ "type": "build",
+ "name": "ra6m5_ek"
+ }
+ ]
+ },
+ {
+ "name": "ra8m1_ek",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "ra8m1_ek"
+ },
+ {
+ "type": "build",
+ "name": "ra8m1_ek"
+ }
+ ]
+ },
+ {
+ "name": "raspberry_pi_pico",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "raspberry_pi_pico"
+ },
+ {
+ "type": "build",
+ "name": "raspberry_pi_pico"
+ }
+ ]
+ },
+ {
+ "name": "raspberry_pi_pico2",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "raspberry_pi_pico2"
+ },
+ {
+ "type": "build",
+ "name": "raspberry_pi_pico2"
+ }
+ ]
+ },
+ {
+ "name": "raspberrypi_cm4",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "raspberrypi_cm4"
+ },
+ {
+ "type": "build",
+ "name": "raspberrypi_cm4"
+ }
+ ]
+ },
+ {
+ "name": "raspberrypi_zero",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "raspberrypi_zero"
+ },
+ {
+ "type": "build",
+ "name": "raspberrypi_zero"
+ }
+ ]
+ },
+ {
+ "name": "raspberrypi_zero2",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "raspberrypi_zero2"
+ },
+ {
+ "type": "build",
+ "name": "raspberrypi_zero2"
+ }
+ ]
+ },
+ {
+ "name": "samd11_xplained",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "samd11_xplained"
+ },
+ {
+ "type": "build",
+ "name": "samd11_xplained"
+ }
+ ]
+ },
+ {
+ "name": "same54_xplained",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "same54_xplained"
+ },
+ {
+ "type": "build",
+ "name": "same54_xplained"
+ }
+ ]
+ },
+ {
+ "name": "samg55_xplained",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "samg55_xplained"
+ },
+ {
+ "type": "build",
+ "name": "samg55_xplained"
+ }
+ ]
+ },
+ {
+ "name": "saml22_feather",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "saml22_feather"
+ },
+ {
+ "type": "build",
+ "name": "saml22_feather"
+ }
+ ]
+ },
+ {
+ "name": "seeeduino_xiao",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "seeeduino_xiao"
+ },
+ {
+ "type": "build",
+ "name": "seeeduino_xiao"
+ }
+ ]
+ },
+ {
+ "name": "sensorwatch_m0",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "sensorwatch_m0"
+ },
+ {
+ "type": "build",
+ "name": "sensorwatch_m0"
+ }
+ ]
+ },
+ {
+ "name": "sipeed_longan_nano",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "sipeed_longan_nano"
+ },
+ {
+ "type": "build",
+ "name": "sipeed_longan_nano"
+ }
+ ]
+ },
+ {
+ "name": "sparkfun_samd21_mini_usb",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "sparkfun_samd21_mini_usb"
+ },
+ {
+ "type": "build",
+ "name": "sparkfun_samd21_mini_usb"
+ }
+ ]
+ },
+ {
+ "name": "stlinkv3mini",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stlinkv3mini"
+ },
+ {
+ "type": "build",
+ "name": "stlinkv3mini"
+ }
+ ]
+ },
+ {
+ "name": "stm32c071nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32c071nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32c071nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32f070rbnucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f070rbnucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32f070rbnucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32f072disco",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f072disco"
+ },
+ {
+ "type": "build",
+ "name": "stm32f072disco"
+ }
+ ]
+ },
+ {
+ "name": "stm32f072eval",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f072eval"
+ },
+ {
+ "type": "build",
+ "name": "stm32f072eval"
+ }
+ ]
+ },
+ {
+ "name": "stm32f103_bluepill",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f103_bluepill"
+ },
+ {
+ "type": "build",
+ "name": "stm32f103_bluepill"
+ }
+ ]
+ },
+ {
+ "name": "stm32f103_mini_2",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f103_mini_2"
+ },
+ {
+ "type": "build",
+ "name": "stm32f103_mini_2"
+ }
+ ]
+ },
+ {
+ "name": "stm32f103ze_iar",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f103ze_iar"
+ },
+ {
+ "type": "build",
+ "name": "stm32f103ze_iar"
+ }
+ ]
+ },
+ {
+ "name": "stm32f207nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f207nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32f207nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32f303disco",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f303disco"
+ },
+ {
+ "type": "build",
+ "name": "stm32f303disco"
+ }
+ ]
+ },
+ {
+ "name": "stm32f401blackpill",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f401blackpill"
+ },
+ {
+ "type": "build",
+ "name": "stm32f401blackpill"
+ }
+ ]
+ },
+ {
+ "name": "stm32f407blackvet",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f407blackvet"
+ },
+ {
+ "type": "build",
+ "name": "stm32f407blackvet"
+ }
+ ]
+ },
+ {
+ "name": "stm32f407disco",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f407disco"
+ },
+ {
+ "type": "build",
+ "name": "stm32f407disco"
+ }
+ ]
+ },
+ {
+ "name": "stm32f411blackpill",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f411blackpill"
+ },
+ {
+ "type": "build",
+ "name": "stm32f411blackpill"
+ }
+ ]
+ },
+ {
+ "name": "stm32f411disco",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f411disco"
+ },
+ {
+ "type": "build",
+ "name": "stm32f411disco"
+ }
+ ]
+ },
+ {
+ "name": "stm32f412disco",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f412disco"
+ },
+ {
+ "type": "build",
+ "name": "stm32f412disco"
+ }
+ ]
+ },
+ {
+ "name": "stm32f412nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f412nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32f412nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32f439nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f439nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32f439nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32f723disco",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f723disco"
+ },
+ {
+ "type": "build",
+ "name": "stm32f723disco"
+ }
+ ]
+ },
+ {
+ "name": "stm32f746disco",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f746disco"
+ },
+ {
+ "type": "build",
+ "name": "stm32f746disco"
+ }
+ ]
+ },
+ {
+ "name": "stm32f746nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f746nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32f746nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32f767nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f767nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32f767nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32f769disco",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32f769disco"
+ },
+ {
+ "type": "build",
+ "name": "stm32f769disco"
+ }
+ ]
+ },
+ {
+ "name": "stm32g0b1nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32g0b1nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32g0b1nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32g474nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32g474nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32g474nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32g491nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32g491nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32g491nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32h503nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32h503nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32h503nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32h563nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32h563nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32h563nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32h573i_dk",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32h573i_dk"
+ },
+ {
+ "type": "build",
+ "name": "stm32h573i_dk"
+ }
+ ]
+ },
+ {
+ "name": "stm32h723nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32h723nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32h723nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32h743eval",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32h743eval"
+ },
+ {
+ "type": "build",
+ "name": "stm32h743eval"
+ }
+ ]
+ },
+ {
+ "name": "stm32h743nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32h743nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32h743nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32h745disco",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32h745disco"
+ },
+ {
+ "type": "build",
+ "name": "stm32h745disco"
+ }
+ ]
+ },
+ {
+ "name": "stm32h750_weact",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32h750_weact"
+ },
+ {
+ "type": "build",
+ "name": "stm32h750_weact"
+ }
+ ]
+ },
+ {
+ "name": "stm32h750bdk",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32h750bdk"
+ },
+ {
+ "type": "build",
+ "name": "stm32h750bdk"
+ }
+ ]
+ },
+ {
+ "name": "stm32h7s3nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32h7s3nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32h7s3nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32l052dap52",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32l052dap52"
+ },
+ {
+ "type": "build",
+ "name": "stm32l052dap52"
+ }
+ ]
+ },
+ {
+ "name": "stm32l0538disco",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32l0538disco"
+ },
+ {
+ "type": "build",
+ "name": "stm32l0538disco"
+ }
+ ]
+ },
+ {
+ "name": "stm32l412nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32l412nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32l412nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32l476disco",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32l476disco"
+ },
+ {
+ "type": "build",
+ "name": "stm32l476disco"
+ }
+ ]
+ },
+ {
+ "name": "stm32l4p5nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32l4p5nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32l4p5nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32l4r5nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32l4r5nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32l4r5nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32u545nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32u545nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32u545nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32u575eval",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32u575eval"
+ },
+ {
+ "type": "build",
+ "name": "stm32u575eval"
+ }
+ ]
+ },
+ {
+ "name": "stm32u575nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32u575nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32u575nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32u5a5nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32u5a5nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32u5a5nucleo"
+ }
+ ]
+ },
+ {
+ "name": "stm32wb55nucleo",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "stm32wb55nucleo"
+ },
+ {
+ "type": "build",
+ "name": "stm32wb55nucleo"
+ }
+ ]
+ },
+ {
+ "name": "teensy_35",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "teensy_35"
+ },
+ {
+ "type": "build",
+ "name": "teensy_35"
+ }
+ ]
+ },
+ {
+ "name": "teensy_40",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "teensy_40"
+ },
+ {
+ "type": "build",
+ "name": "teensy_40"
+ }
+ ]
+ },
+ {
+ "name": "teensy_41",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "teensy_41"
+ },
+ {
+ "type": "build",
+ "name": "teensy_41"
+ }
+ ]
+ },
+ {
+ "name": "trinket_m0",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "trinket_m0"
+ },
+ {
+ "type": "build",
+ "name": "trinket_m0"
+ }
+ ]
+ },
+ {
+ "name": "uno_r4",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "uno_r4"
+ },
+ {
+ "type": "build",
+ "name": "uno_r4"
+ }
+ ]
+ },
+ {
+ "name": "waveshare_openh743i",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "waveshare_openh743i"
+ },
+ {
+ "type": "build",
+ "name": "waveshare_openh743i"
+ }
+ ]
+ },
+ {
+ "name": "xmc4500_relax",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "xmc4500_relax"
+ },
+ {
+ "type": "build",
+ "name": "xmc4500_relax"
+ }
+ ]
+ },
+ {
+ "name": "xmc4700_relax",
+ "steps": [
+ {
+ "type": "configure",
+ "name": "xmc4700_relax"
+ },
+ {
+ "type": "build",
+ "name": "xmc4700_relax"
+ }
+ ]
+ }
+ ]
+}
diff --git a/hw/bsp/board.c b/hw/bsp/board.c
index 5bcdb7f15..0e0fa4ac6 100644
--- a/hw/bsp/board.c
+++ b/hw/bsp/board.c
@@ -64,9 +64,7 @@ int sys_read(int fhdl, char *buf, size_t count) {
#endif
#elif defined(LOGGER_SWO)
-// Logging with SWO for ARM Cortex
-#include "board_mcu.h"
-
+// Logging with SWO for ARM Cortex-M
int sys_write (int fhdl, const char *buf, size_t count) {
(void) fhdl;
uint8_t const* buf8 = (uint8_t const*) buf;
diff --git a/hw/bsp/board_mcu.h b/hw/bsp/board_mcu.h
deleted file mode 100644
index e720cd747..000000000
--- a/hw/bsp/board_mcu.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * 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_MCU_H_
-#define BOARD_MCU_H_
-
-#include "tusb_option.h"
-
-//--------------------------------------------------------------------+
-// Low Level MCU header include. Example should be
-// platform independent and mostly doesn't need to include this file.
-// However there are still certain situation where this file is needed:
-// - FreeRTOSConfig.h to set up correct clock and NVIC interrupts for ARM Cortex
-// - SWO logging for Cortex M with ITM_SendChar() / ITM_ReceiveChar()
-//--------------------------------------------------------------------+
-
-// Include order follows OPT_MCU_ number
-#if TU_CHECK_MCU(OPT_MCU_LPC11UXX, OPT_MCU_LPC13XX, OPT_MCU_LPC15XX) || \
- TU_CHECK_MCU(OPT_MCU_LPC175X_6X, OPT_MCU_LPC177X_8X, OPT_MCU_LPC18XX) || \
- TU_CHECK_MCU(OPT_MCU_LPC40XX, OPT_MCU_LPC43XX)
- #include "chip.h"
-
-#elif TU_CHECK_MCU(OPT_MCU_LPC51UXX, OPT_MCU_LPC54XXX, OPT_MCU_LPC55XX, OPT_MCU_MCXN9)
- #include "fsl_device_registers.h"
-
-#elif TU_CHECK_MCU(OPT_MCU_KINETIS_KL, OPT_MCU_KINETIS_K32L, OPT_MCU_KINETIS_K)
- #include "fsl_device_registers.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_NRF5X
- #include "nrf.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_SAMD11 || CFG_TUSB_MCU == OPT_MCU_SAMD21 || \
- CFG_TUSB_MCU == OPT_MCU_SAMD51 || CFG_TUSB_MCU == OPT_MCU_SAME5X || \
- CFG_TUSB_MCU == OPT_MCU_SAML22 || CFG_TUSB_MCU == OPT_MCU_SAML21
- #include "sam.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_SAMG
- #undef LITTLE_ENDIAN // hack to suppress "LITTLE_ENDIAN" redefined
- #include "sam.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32F0
- #include "stm32f0xx.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32F1
- #include "stm32f1xx.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32F2
- #include "stm32f2xx.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32F3
- #include "stm32f3xx.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32F4
- #include "stm32f4xx.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32F7
- #include "stm32f7xx.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32G4
- #include "stm32g4xx.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32H5
- #include "stm32h5xx.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32H7
- #include "stm32h7xx.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32L0
- #include "stm32l0xx.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32L1
- #include "stm32l1xx.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32L4
- #include "stm32l4xx.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32WB
- #include "stm32wbxx.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32U5
- #include "stm32u5xx.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32G0
- #include "stm32g0xx.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_STM32C0
- #include "stm32c0xx.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_CXD56
- // no header needed
-
-#elif CFG_TUSB_MCU == OPT_MCU_MSP430x5xx
- #include "msp430.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_MSP432E4
- #include "msp.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_VALENTYUSB_EPTRI
- // no header needed
-
-#elif CFG_TUSB_MCU == OPT_MCU_MIMXRT1XXX
- #include "fsl_device_registers.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_NUC120
- #include "NUC100Series.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_NUC121 || CFG_TUSB_MCU == OPT_MCU_NUC126
- #include "NuMicro.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_NUC505
- #include "NUC505Series.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_ESP32S2
- // no header needed
-
-#elif CFG_TUSB_MCU == OPT_MCU_ESP32S3
- // no header needed
-
-#elif CFG_TUSB_MCU == OPT_MCU_DA1469X
- #include "DA1469xAB.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_RP2040
- #include "pico.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_EFM32GG
- #include "em_device.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_RX63X || CFG_TUSB_MCU == OPT_MCU_RX65X
- // no header needed
-
-#elif CFG_TUSB_MCU == OPT_MCU_RAXXX
- #include "bsp_api.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_GD32VF103
- #include "gd32vf103.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_MM32F327X
- #include "mm32_device.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_XMC4000
- #include "xmc_device.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_TM4C123
- #include "TM4C123.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_CH32F20X
- #include "ch32f20x.h"
-
-#elif TU_CHECK_MCU(OPT_MCU_BCM2711, OPT_MCU_BCM2835, OPT_MCU_BCM2837)
- // no header needed
-
-#elif CFG_TUSB_MCU == OPT_MCU_MAX32690
- #include "max32690.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_MAX32650
- #include "max32650.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_MAX32666
- #include "max32665.h"
-
-#elif CFG_TUSB_MCU == OPT_MCU_MAX78002
- #include "max78002.h"
-
-#else
- #error "Missing MCU header"
-#endif
-
-
-#endif /* BOARD_MCU_H_ */
diff --git a/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.h b/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.h
index 256958088..56f49205c 100644
--- a/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.h
+++ b/hw/bsp/ch32v20x/boards/ch32v203c_r0_1v0/board.h
@@ -13,6 +13,8 @@ extern "C" {
#define LED_PORT GPIOA
#define LED_PIN GPIO_Pin_0
#define LED_STATE_ON 0
+#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE)
+#define LED_MODE GPIO_Mode_Out_OD
#define UART_DEV USART1
#define UART_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE)
diff --git a/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.h b/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.h
index 827226d80..4a040e0df 100644
--- a/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.h
+++ b/hw/bsp/ch32v20x/boards/ch32v203g_r0_1v0/board.h
@@ -13,6 +13,8 @@ extern "C" {
#define LED_PORT GPIOA
#define LED_PIN GPIO_Pin_0
#define LED_STATE_ON 0
+#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE)
+#define LED_MODE GPIO_Mode_Out_OD
#define UART_DEV USART2
#define UART_CLOCK_EN() RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE)
diff --git a/hw/bsp/ch32v20x/boards/nanoch32v203/board.h b/hw/bsp/ch32v20x/boards/nanoch32v203/board.h
index f02fceced..63237861c 100644
--- a/hw/bsp/ch32v20x/boards/nanoch32v203/board.h
+++ b/hw/bsp/ch32v20x/boards/nanoch32v203/board.h
@@ -13,6 +13,8 @@ extern "C" {
#define LED_PORT GPIOA
#define LED_PIN GPIO_Pin_15
#define LED_STATE_ON 0
+#define LED_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE)
+#define LED_MODE GPIO_Mode_Out_OD
#define UART_DEV USART1
#define UART_CLOCK_EN() RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE)
diff --git a/hw/bsp/ch32v20x/family.c b/hw/bsp/ch32v20x/family.c
index 5f52d9447..21ed94b0a 100644
--- a/hw/bsp/ch32v20x/family.c
+++ b/hw/bsp/ch32v20x/family.c
@@ -96,11 +96,11 @@ void board_init(void) {
SysTick_Config(SystemCoreClock / 1000);
#endif
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
+ LED_CLOCK_EN();
GPIO_InitTypeDef GPIO_InitStructure = {
.GPIO_Pin = LED_PIN,
- .GPIO_Mode = GPIO_Mode_Out_OD,
+ .GPIO_Mode = LED_MODE,
.GPIO_Speed = GPIO_Speed_10MHz,
};
GPIO_Init(LED_PORT, &GPIO_InitStructure);
diff --git a/hw/bsp/espressif/boards/family.c b/hw/bsp/espressif/boards/family.c
index 2f9ecfe4d..7049c0415 100644
--- a/hw/bsp/espressif/boards/family.c
+++ b/hw/bsp/espressif/boards/family.c
@@ -162,7 +162,6 @@ int board_getchar(void) {
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 3, 0)
#include "esp_private/usb_phy.h"
-#include "soc/usb_pins.h"
static usb_phy_handle_t phy_hdl;
diff --git a/hw/bsp/family_support.cmake b/hw/bsp/family_support.cmake
index 04d537376..3a6890690 100644
--- a/hw/bsp/family_support.cmake
+++ b/hw/bsp/family_support.cmake
@@ -12,7 +12,7 @@ set(UF2CONV_PY ${TOP}/tools/uf2/utils/uf2conv.py)
# RTOS
#-------------------------------------------------------------
if (NOT DEFINED RTOS)
- set(RTOS noos)
+ set(RTOS noos CACHE STRING "RTOS")
endif ()
#-------------------------------------------------------------
@@ -270,10 +270,6 @@ function(family_add_tinyusb TARGET OPT_MCU)
# Add TinyUSB sources, include and common define
tinyusb_target_add(${TARGET})
-
- # path to tusb_config.h
- target_include_directories(${TARGET} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
-
target_compile_definitions(${TARGET} PUBLIC CFG_TUSB_MCU=${OPT_MCU})
if (DEFINED LOG)
target_compile_definitions(${TARGET} PUBLIC CFG_TUSB_DEBUG=${LOG})
@@ -399,7 +395,11 @@ endfunction()
# Add flash jlink target
function(family_flash_jlink TARGET)
if (NOT DEFINED JLINKEXE)
- set(JLINKEXE JLinkExe)
+ if(CMAKE_HOST_WIN32)
+ set(JLINKEXE JLink.exe)
+ else()
+ set(JLINKEXE JLinkExe)
+ endif()
endif ()
if (NOT DEFINED JLINK_IF)
@@ -472,6 +472,10 @@ function(family_flash_openocd TARGET)
set(OPENOCD_OPTION2 "")
endif ()
+ if (DEFINED OPENOCD_SERIAL)
+ set(OPENOCD_OPTION "-c \"adapter serial ${OPENOCD_SERIAL}\" ${OPENOCD_OPTION}")
+ endif ()
+
separate_arguments(OPTION_LIST UNIX_COMMAND ${OPENOCD_OPTION})
separate_arguments(OPTION_LIST2 UNIX_COMMAND ${OPENOCD_OPTION2})
diff --git a/hw/bsp/imxrt/boards/mimxrt1015_evk/board/clock_config.c b/hw/bsp/imxrt/boards/mimxrt1015_evk/board/clock_config.c
index ae1aa7fb1..b9e4851bf 100644
--- a/hw/bsp/imxrt/boards/mimxrt1015_evk/board/clock_config.c
+++ b/hw/bsp/imxrt/boards/mimxrt1015_evk/board/clock_config.c
@@ -15,11 +15,11 @@
/* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
!!GlobalInfo
-product: Clocks v11.0
+product: Clocks v15.0
processor: MIMXRT1015xxxxx
package_id: MIMXRT1015DAF5A
mcu_data: ksdk2_0
-processor_version: 13.0.2
+processor_version: 24.12.10
board: MIMXRT1015-EVK
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/
diff --git a/hw/bsp/imxrt/boards/mimxrt1015_evk/board/clock_config.h b/hw/bsp/imxrt/boards/mimxrt1015_evk/board/clock_config.h
index 2acdb16a7..cccbe487a 100644
--- a/hw/bsp/imxrt/boards/mimxrt1015_evk/board/clock_config.h
+++ b/hw/bsp/imxrt/boards/mimxrt1015_evk/board/clock_config.h
@@ -36,39 +36,39 @@ void BOARD_InitBootClocks(void);
#define BOARD_BOOTCLOCKRUN_CORE_CLOCK 500000000U /*!< Core clock frequency: 500000000Hz */
/* Clock outputs (values are in Hz): */
-#define BOARD_BOOTCLOCKRUN_AHB_CLK_ROOT 500000000UL
-#define BOARD_BOOTCLOCKRUN_CKIL_SYNC_CLK_ROOT 32768UL
-#define BOARD_BOOTCLOCKRUN_CLKO1_CLK 0UL
-#define BOARD_BOOTCLOCKRUN_CLKO2_CLK 0UL
-#define BOARD_BOOTCLOCKRUN_CLK_1M 1000000UL
-#define BOARD_BOOTCLOCKRUN_CLK_24M 24000000UL
-#define BOARD_BOOTCLOCKRUN_ENET_500M_REF_CLK 500000000UL
-#define BOARD_BOOTCLOCKRUN_FLEXIO1_CLK_ROOT 30000000UL
-#define BOARD_BOOTCLOCKRUN_FLEXSPI_CLK_ROOT 196363636UL
-#define BOARD_BOOTCLOCKRUN_GPT1_IPG_CLK_HIGHFREQ 62500000UL
-#define BOARD_BOOTCLOCKRUN_GPT2_IPG_CLK_HIGHFREQ 62500000UL
-#define BOARD_BOOTCLOCKRUN_IPG_CLK_ROOT 125000000UL
-#define BOARD_BOOTCLOCKRUN_LPI2C_CLK_ROOT 60000000UL
-#define BOARD_BOOTCLOCKRUN_LPSPI_CLK_ROOT 105600000UL
-#define BOARD_BOOTCLOCKRUN_MQS_MCLK 63529411UL
-#define BOARD_BOOTCLOCKRUN_PERCLK_CLK_ROOT 62500000UL
-#define BOARD_BOOTCLOCKRUN_SAI1_CLK_ROOT 63529411UL
-#define BOARD_BOOTCLOCKRUN_SAI1_MCLK1 63529411UL
-#define BOARD_BOOTCLOCKRUN_SAI1_MCLK2 63529411UL
-#define BOARD_BOOTCLOCKRUN_SAI1_MCLK3 30000000UL
-#define BOARD_BOOTCLOCKRUN_SAI2_CLK_ROOT 63529411UL
-#define BOARD_BOOTCLOCKRUN_SAI2_MCLK1 63529411UL
-#define BOARD_BOOTCLOCKRUN_SAI2_MCLK2 0UL
-#define BOARD_BOOTCLOCKRUN_SAI2_MCLK3 30000000UL
-#define BOARD_BOOTCLOCKRUN_SAI3_CLK_ROOT 63529411UL
-#define BOARD_BOOTCLOCKRUN_SAI3_MCLK1 63529411UL
-#define BOARD_BOOTCLOCKRUN_SAI3_MCLK2 0UL
-#define BOARD_BOOTCLOCKRUN_SAI3_MCLK3 30000000UL
-#define BOARD_BOOTCLOCKRUN_SPDIF0_CLK_ROOT 30000000UL
-#define BOARD_BOOTCLOCKRUN_SPDIF0_EXTCLK_OUT 0UL
-#define BOARD_BOOTCLOCKRUN_TRACE_CLK_ROOT 117333333UL
-#define BOARD_BOOTCLOCKRUN_UART_CLK_ROOT 80000000UL
-#define BOARD_BOOTCLOCKRUN_USBPHY1_CLK 480000000UL
+#define BOARD_BOOTCLOCKRUN_AHB_CLK_ROOT 500000000UL /* Clock consumers of AHB_CLK_ROOT output : AIPSTZ1, AIPSTZ2, AIPSTZ3, AIPSTZ4, ARM, FLEXSPI */
+#define BOARD_BOOTCLOCKRUN_CKIL_SYNC_CLK_ROOT 32768UL /* Clock consumers of CKIL_SYNC_CLK_ROOT output : CSU, EWM, GPT1, GPT2, KPP, PIT, RTWDOG, SNVS, SPDIF, TEMPMON, USB, WDOG1, WDOG2 */
+#define BOARD_BOOTCLOCKRUN_CLKO1_CLK 0UL /* Clock consumers of CLKO1_CLK output : N/A */
+#define BOARD_BOOTCLOCKRUN_CLKO2_CLK 0UL /* Clock consumers of CLKO2_CLK output : N/A */
+#define BOARD_BOOTCLOCKRUN_CLK_1M 1000000UL /* Clock consumers of CLK_1M output : EWM, RTWDOG */
+#define BOARD_BOOTCLOCKRUN_CLK_24M 24000000UL /* Clock consumers of CLK_24M output : GPT1, GPT2 */
+#define BOARD_BOOTCLOCKRUN_ENET_500M_REF_CLK 500000000UL /* Clock consumers of ENET_500M_REF_CLK output : N/A */
+#define BOARD_BOOTCLOCKRUN_FLEXIO1_CLK_ROOT 30000000UL /* Clock consumers of FLEXIO1_CLK_ROOT output : FLEXIO1 */
+#define BOARD_BOOTCLOCKRUN_FLEXSPI_CLK_ROOT 196363636UL /* Clock consumers of FLEXSPI_CLK_ROOT output : FLEXSPI */
+#define BOARD_BOOTCLOCKRUN_GPT1_IPG_CLK_HIGHFREQ 62500000UL /* Clock consumers of GPT1_ipg_clk_highfreq output : GPT1 */
+#define BOARD_BOOTCLOCKRUN_GPT2_IPG_CLK_HIGHFREQ 62500000UL /* Clock consumers of GPT2_ipg_clk_highfreq output : GPT2 */
+#define BOARD_BOOTCLOCKRUN_IPG_CLK_ROOT 125000000UL /* Clock consumers of IPG_CLK_ROOT output : ADC1, ADC_ETC, AOI, ARM, BEE, CCM, CSU, DCDC, DCP, DMA0, DMAMUX, ENC1, EWM, FLEXIO1, FLEXRAM, FLEXSPI, GPC, GPIO1, GPIO2, GPIO3, GPIO5, IOMUXC, KPP, LPI2C1, LPI2C2, LPSPI1, LPSPI2, LPUART1, LPUART2, LPUART3, LPUART4, NVIC, OCOTP, PWM1, RTWDOG, SAI1, SAI2, SAI3, SNVS, SPDIF, SRC, TEMPMON, TMR1, TRNG, USB, WDOG1, WDOG2, XBARA, XBARB */
+#define BOARD_BOOTCLOCKRUN_LPI2C_CLK_ROOT 60000000UL /* Clock consumers of LPI2C_CLK_ROOT output : LPI2C1, LPI2C2 */
+#define BOARD_BOOTCLOCKRUN_LPSPI_CLK_ROOT 105600000UL /* Clock consumers of LPSPI_CLK_ROOT output : LPSPI1, LPSPI2 */
+#define BOARD_BOOTCLOCKRUN_MQS_MCLK 63529411UL /* Clock consumers of MQS_MCLK output : N/A */
+#define BOARD_BOOTCLOCKRUN_PERCLK_CLK_ROOT 62500000UL /* Clock consumers of PERCLK_CLK_ROOT output : GPT1, GPT2, PIT */
+#define BOARD_BOOTCLOCKRUN_SAI1_CLK_ROOT 63529411UL /* Clock consumers of SAI1_CLK_ROOT output : N/A */
+#define BOARD_BOOTCLOCKRUN_SAI1_MCLK1 63529411UL /* Clock consumers of SAI1_MCLK1 output : SAI1 */
+#define BOARD_BOOTCLOCKRUN_SAI1_MCLK2 63529411UL /* Clock consumers of SAI1_MCLK2 output : SAI1 */
+#define BOARD_BOOTCLOCKRUN_SAI1_MCLK3 30000000UL /* Clock consumers of SAI1_MCLK3 output : SAI1 */
+#define BOARD_BOOTCLOCKRUN_SAI2_CLK_ROOT 63529411UL /* Clock consumers of SAI2_CLK_ROOT output : N/A */
+#define BOARD_BOOTCLOCKRUN_SAI2_MCLK1 63529411UL /* Clock consumers of SAI2_MCLK1 output : SAI2 */
+#define BOARD_BOOTCLOCKRUN_SAI2_MCLK2 0UL /* Clock consumers of SAI2_MCLK2 output : SAI2 */
+#define BOARD_BOOTCLOCKRUN_SAI2_MCLK3 30000000UL /* Clock consumers of SAI2_MCLK3 output : SAI2 */
+#define BOARD_BOOTCLOCKRUN_SAI3_CLK_ROOT 63529411UL /* Clock consumers of SAI3_CLK_ROOT output : N/A */
+#define BOARD_BOOTCLOCKRUN_SAI3_MCLK1 63529411UL /* Clock consumers of SAI3_MCLK1 output : SAI3 */
+#define BOARD_BOOTCLOCKRUN_SAI3_MCLK2 0UL /* Clock consumers of SAI3_MCLK2 output : SAI3 */
+#define BOARD_BOOTCLOCKRUN_SAI3_MCLK3 30000000UL /* Clock consumers of SAI3_MCLK3 output : SAI3 */
+#define BOARD_BOOTCLOCKRUN_SPDIF0_CLK_ROOT 30000000UL /* Clock consumers of SPDIF0_CLK_ROOT output : SPDIF */
+#define BOARD_BOOTCLOCKRUN_SPDIF0_EXTCLK_OUT 0UL /* Clock consumers of SPDIF0_EXTCLK_OUT output : SPDIF */
+#define BOARD_BOOTCLOCKRUN_TRACE_CLK_ROOT 117333333UL /* Clock consumers of TRACE_CLK_ROOT output : ARM */
+#define BOARD_BOOTCLOCKRUN_UART_CLK_ROOT 80000000UL /* Clock consumers of UART_CLK_ROOT output : LPUART1, LPUART2, LPUART3, LPUART4 */
+#define BOARD_BOOTCLOCKRUN_USBPHY1_CLK 480000000UL /* Clock consumers of USBPHY1_CLK output : TEMPMON, USB */
/*! @brief Usb1 PLL set for BOARD_BootClockRUN configuration.
*/
diff --git a/hw/bsp/imxrt/boards/mimxrt1015_evk/board/pin_mux.c b/hw/bsp/imxrt/boards/mimxrt1015_evk/board/pin_mux.c
index 97224a332..76c1dae70 100644
--- a/hw/bsp/imxrt/boards/mimxrt1015_evk/board/pin_mux.c
+++ b/hw/bsp/imxrt/boards/mimxrt1015_evk/board/pin_mux.c
@@ -6,11 +6,11 @@
/*
* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
!!GlobalInfo
-product: Pins v13.1
+product: Pins v17.0
processor: MIMXRT1015xxxxx
package_id: MIMXRT1015DAF5A
mcu_data: ksdk2_0
-processor_version: 13.0.2
+processor_version: 24.12.10
board: MIMXRT1015-EVK
external_user_signals: {}
pin_labels:
@@ -32,6 +32,7 @@ power_domains: {NVCC_GPIO: '3.3'}
* END ****************************************************************************************************************/
void BOARD_InitBootPins(void) {
BOARD_InitPins();
+ BOARD_InitDEBUG_UARTPins();
}
/*
@@ -40,8 +41,6 @@ BOARD_InitPins:
- options: {callFromInitBoot: 'true', coreID: core0, enableClock: 'true'}
- pin_list:
- {pin_num: '1', peripheral: GPIO2, signal: 'gpio_io, 09', pin_signal: GPIO_EMC_09, direction: INPUT, pull_keeper_select: Pull, pull_up_down_config: Pull_Up_47K_Ohm}
- - {pin_num: '68', peripheral: LPUART1, signal: RX, pin_signal: GPIO_AD_B0_07, pull_up_down_config: Pull_Down_100K_Ohm}
- - {pin_num: '72', peripheral: LPUART1, signal: TX, pin_signal: GPIO_AD_B0_06}
- {pin_num: '21', peripheral: GPIO3, signal: 'gpio_io, 21', pin_signal: GPIO_SD_B1_01, direction: OUTPUT}
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS ***********
*/
@@ -73,15 +72,11 @@ void BOARD_InitPins(void) {
/* Initialize GPIO functionality on GPIO_SD_B1_01 (pin 21) */
GPIO_PinInit(GPIO3, 21U, &USER_LED_config);
- IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_06_LPUART1_TX, 0U);
- IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_07_LPUART1_RX, 0U);
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_09_GPIO2_IO09, 0U);
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_01_GPIO3_IO21, 0U);
- IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_07_LPUART1_RX, 0x10B0U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_09_GPIO2_IO09, 0x70B0U);
}
-
/*
* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
BOARD_InitQSPIPins:
@@ -113,6 +108,30 @@ void BOARD_InitQSPIPins(void) {
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_11_FLEXSPI_A_SS0_B, 0U);
}
+/*
+ * TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
+BOARD_InitDEBUG_UARTPins:
+- options: {callFromInitBoot: 'true', coreID: core0, enableClock: 'true'}
+- pin_list:
+ - {pin_num: '68', peripheral: LPUART1, signal: RX, pin_signal: GPIO_AD_B0_07, slew_rate: Slow}
+ - {pin_num: '72', peripheral: LPUART1, signal: TX, pin_signal: GPIO_AD_B0_06, slew_rate: Slow}
+ * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS ***********
+ */
+
+/* FUNCTION ************************************************************************************************************
+ *
+ * Function Name : BOARD_InitDEBUG_UARTPins
+ * Description : Configures pin routing and optionally pin electrical features.
+ *
+ * END ****************************************************************************************************************/
+void BOARD_InitDEBUG_UARTPins(void) {
+ CLOCK_EnableClock(kCLOCK_Iomuxc);
+
+ IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_06_LPUART1_TX, 0U);
+ IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_07_LPUART1_RX, 0U);
+ IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_06_LPUART1_TX, 0x10B0U);
+ IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_07_LPUART1_RX, 0x10B0U);
+}
/***********************************************************************************************************************
* EOF
**********************************************************************************************************************/
diff --git a/hw/bsp/imxrt/boards/mimxrt1015_evk/board/pin_mux.h b/hw/bsp/imxrt/boards/mimxrt1015_evk/board/pin_mux.h
index c9cbe3b72..2f3bf2c4c 100644
--- a/hw/bsp/imxrt/boards/mimxrt1015_evk/board/pin_mux.h
+++ b/hw/bsp/imxrt/boards/mimxrt1015_evk/board/pin_mux.h
@@ -37,7 +37,7 @@ extern "C" {
*/
void BOARD_InitBootPins(void);
-/* GPIO_EMC_09 (number 1), USER_BUTTON */
+/* GPIO_EMC_09 (number 1), USER_BUTTON/SW4 */
/* Routed pin properties */
#define BOARD_INITPINS_USER_BUTTON_PERIPHERAL GPIO2 /*!< Peripheral name */
#define BOARD_INITPINS_USER_BUTTON_SIGNAL gpio_io /*!< Signal name */
@@ -51,16 +51,6 @@ void BOARD_InitBootPins(void);
#define BOARD_INITPINS_USER_BUTTON_PIN 9U /*!< PORT pin number */
#define BOARD_INITPINS_USER_BUTTON_PIN_MASK (1U << 9U) /*!< PORT pin mask */
-/* GPIO_AD_B0_07 (number 68), LPUART1_RXD */
-/* Routed pin properties */
-#define BOARD_INITPINS_UART1_RXD_PERIPHERAL LPUART1 /*!< Peripheral name */
-#define BOARD_INITPINS_UART1_RXD_SIGNAL RX /*!< Signal name */
-
-/* GPIO_AD_B0_06 (number 72), LPUART1_TXD */
-/* Routed pin properties */
-#define BOARD_INITPINS_UART1_TXD_PERIPHERAL LPUART1 /*!< Peripheral name */
-#define BOARD_INITPINS_UART1_TXD_SIGNAL TX /*!< Signal name */
-
/* GPIO_SD_B1_01 (number 21), GPIO SD_B1_01 */
/* Routed pin properties */
#define BOARD_INITPINS_USER_LED_PERIPHERAL GPIO3 /*!< Peripheral name */
@@ -69,6 +59,7 @@ void BOARD_InitBootPins(void);
/* Symbols to be used with GPIO driver */
#define BOARD_INITPINS_USER_LED_GPIO GPIO3 /*!< GPIO peripheral base pointer */
+#define BOARD_INITPINS_USER_LED_INIT_GPIO_VALUE 0U /*!< GPIO output initial state */
#define BOARD_INITPINS_USER_LED_GPIO_PIN 21U /*!< GPIO pin number */
#define BOARD_INITPINS_USER_LED_GPIO_PIN_MASK (1U << 21U) /*!< GPIO pin mask */
#define BOARD_INITPINS_USER_LED_PORT GPIO3 /*!< PORT peripheral base pointer */
@@ -119,6 +110,23 @@ void BOARD_InitPins(void);
*/
void BOARD_InitQSPIPins(void);
+/* GPIO_AD_B0_07 (number 68), LPUART1_RXD */
+/* Routed pin properties */
+#define BOARD_INITDEBUG_UARTPINS_UART1_RXD_PERIPHERAL LPUART1 /*!< Peripheral name */
+#define BOARD_INITDEBUG_UARTPINS_UART1_RXD_SIGNAL RX /*!< Signal name */
+
+/* GPIO_AD_B0_06 (number 72), LPUART1_TXD */
+/* Routed pin properties */
+#define BOARD_INITDEBUG_UARTPINS_UART1_TXD_PERIPHERAL LPUART1 /*!< Peripheral name */
+#define BOARD_INITDEBUG_UARTPINS_UART1_TXD_SIGNAL TX /*!< Signal name */
+
+
+/*!
+ * @brief Configures pin routing and optionally pin electrical features.
+ *
+ */
+void BOARD_InitDEBUG_UARTPins(void);
+
#if defined(__cplusplus)
}
#endif
diff --git a/hw/bsp/imxrt/boards/mimxrt1015_evk/mimxrt1015_evk.mex b/hw/bsp/imxrt/boards/mimxrt1015_evk/mimxrt1015_evk.mex
index 88265d32e..917bed375 100644
--- a/hw/bsp/imxrt/boards/mimxrt1015_evk/mimxrt1015_evk.mex
+++ b/hw/bsp/imxrt/boards/mimxrt1015_evk/mimxrt1015_evk.mex
@@ -1,5 +1,5 @@
-
+
MIMXRT1015xxxxx
MIMXRT1015DAF5A
@@ -13,19 +13,18 @@
true
- false
false
true
false
-
+
- 13.0.2
+ 24.12.10
@@ -45,12 +44,7 @@
true
-
-
- true
-
-
-
+
true
@@ -79,12 +73,6 @@
-
-
-
-
-
-
@@ -100,7 +88,7 @@
true
-
+
true
@@ -125,15 +113,52 @@
+
+ Configures pin routing and optionally pin electrical features.
+
+ true
+ core0
+ true
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
- 13.0.2
+ 24.12.10
diff --git a/hw/bsp/imxrt/boards/mimxrt1064_evk/board/clock_config.c b/hw/bsp/imxrt/boards/mimxrt1064_evk/board/clock_config.c
index 778ab02f2..be684faee 100644
--- a/hw/bsp/imxrt/boards/mimxrt1064_evk/board/clock_config.c
+++ b/hw/bsp/imxrt/boards/mimxrt1064_evk/board/clock_config.c
@@ -15,11 +15,11 @@
/* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
!!GlobalInfo
-product: Clocks v11.0
+product: Clocks v15.0
processor: MIMXRT1064xxxxA
package_id: MIMXRT1064DVL6A
mcu_data: ksdk2_0
-processor_version: 13.0.2
+processor_version: 24.12.10
board: MIMXRT1064-EVK
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/
diff --git a/hw/bsp/imxrt/boards/mimxrt1064_evk/board/clock_config.h b/hw/bsp/imxrt/boards/mimxrt1064_evk/board/clock_config.h
index 7ce24b6f4..2fa713c0d 100644
--- a/hw/bsp/imxrt/boards/mimxrt1064_evk/board/clock_config.h
+++ b/hw/bsp/imxrt/boards/mimxrt1064_evk/board/clock_config.h
@@ -36,56 +36,56 @@ void BOARD_InitBootClocks(void);
#define BOARD_BOOTCLOCKRUN_CORE_CLOCK 600000000U /*!< Core clock frequency: 600000000Hz */
/* Clock outputs (values are in Hz): */
-#define BOARD_BOOTCLOCKRUN_AHB_CLK_ROOT 600000000UL
-#define BOARD_BOOTCLOCKRUN_CAN_CLK_ROOT 40000000UL
-#define BOARD_BOOTCLOCKRUN_CKIL_SYNC_CLK_ROOT 32768UL
-#define BOARD_BOOTCLOCKRUN_CLKO1_CLK 0UL
-#define BOARD_BOOTCLOCKRUN_CLKO2_CLK 0UL
-#define BOARD_BOOTCLOCKRUN_CLK_1M 1000000UL
-#define BOARD_BOOTCLOCKRUN_CLK_24M 24000000UL
-#define BOARD_BOOTCLOCKRUN_CSI_CLK_ROOT 12000000UL
-#define BOARD_BOOTCLOCKRUN_ENET2_125M_CLK 1200000UL
-#define BOARD_BOOTCLOCKRUN_ENET2_REF_CLK 0UL
-#define BOARD_BOOTCLOCKRUN_ENET2_TX_CLK 0UL
-#define BOARD_BOOTCLOCKRUN_ENET_125M_CLK 2400000UL
-#define BOARD_BOOTCLOCKRUN_ENET_25M_REF_CLK 1200000UL
-#define BOARD_BOOTCLOCKRUN_ENET_REF_CLK 0UL
-#define BOARD_BOOTCLOCKRUN_ENET_TX_CLK 0UL
-#define BOARD_BOOTCLOCKRUN_FLEXIO1_CLK_ROOT 30000000UL
-#define BOARD_BOOTCLOCKRUN_FLEXIO2_CLK_ROOT 30000000UL
-#define BOARD_BOOTCLOCKRUN_FLEXSPI2_CLK_ROOT 130909090UL
-#define BOARD_BOOTCLOCKRUN_FLEXSPI_CLK_ROOT 130909090UL
-#define BOARD_BOOTCLOCKRUN_GPT1_IPG_CLK_HIGHFREQ 75000000UL
-#define BOARD_BOOTCLOCKRUN_GPT2_IPG_CLK_HIGHFREQ 75000000UL
-#define BOARD_BOOTCLOCKRUN_IPG_CLK_ROOT 150000000UL
-#define BOARD_BOOTCLOCKRUN_LCDIF_CLK_ROOT 67500000UL
-#define BOARD_BOOTCLOCKRUN_LPI2C_CLK_ROOT 60000000UL
-#define BOARD_BOOTCLOCKRUN_LPSPI_CLK_ROOT 105600000UL
-#define BOARD_BOOTCLOCKRUN_LVDS1_CLK 1200000000UL
-#define BOARD_BOOTCLOCKRUN_MQS_MCLK 63529411UL
-#define BOARD_BOOTCLOCKRUN_PERCLK_CLK_ROOT 75000000UL
-#define BOARD_BOOTCLOCKRUN_PLL7_MAIN_CLK 480000000UL
-#define BOARD_BOOTCLOCKRUN_SAI1_CLK_ROOT 63529411UL
-#define BOARD_BOOTCLOCKRUN_SAI1_MCLK1 63529411UL
-#define BOARD_BOOTCLOCKRUN_SAI1_MCLK2 63529411UL
-#define BOARD_BOOTCLOCKRUN_SAI1_MCLK3 30000000UL
-#define BOARD_BOOTCLOCKRUN_SAI2_CLK_ROOT 63529411UL
-#define BOARD_BOOTCLOCKRUN_SAI2_MCLK1 63529411UL
-#define BOARD_BOOTCLOCKRUN_SAI2_MCLK2 0UL
-#define BOARD_BOOTCLOCKRUN_SAI2_MCLK3 30000000UL
-#define BOARD_BOOTCLOCKRUN_SAI3_CLK_ROOT 63529411UL
-#define BOARD_BOOTCLOCKRUN_SAI3_MCLK1 63529411UL
-#define BOARD_BOOTCLOCKRUN_SAI3_MCLK2 0UL
-#define BOARD_BOOTCLOCKRUN_SAI3_MCLK3 30000000UL
-#define BOARD_BOOTCLOCKRUN_SEMC_CLK_ROOT 75000000UL
-#define BOARD_BOOTCLOCKRUN_SPDIF0_CLK_ROOT 30000000UL
-#define BOARD_BOOTCLOCKRUN_SPDIF0_EXTCLK_OUT 0UL
-#define BOARD_BOOTCLOCKRUN_TRACE_CLK_ROOT 132000000UL
-#define BOARD_BOOTCLOCKRUN_UART_CLK_ROOT 80000000UL
-#define BOARD_BOOTCLOCKRUN_USBPHY1_CLK 480000000UL
-#define BOARD_BOOTCLOCKRUN_USBPHY2_CLK 480000000UL
-#define BOARD_BOOTCLOCKRUN_USDHC1_CLK_ROOT 198000000UL
-#define BOARD_BOOTCLOCKRUN_USDHC2_CLK_ROOT 198000000UL
+#define BOARD_BOOTCLOCKRUN_AHB_CLK_ROOT 600000000UL /* Clock consumers of AHB_CLK_ROOT output : AIPSTZ1, AIPSTZ2, AIPSTZ3, AIPSTZ4, ARM, FLEXIO3, FLEXSPI, FLEXSPI2, GPIO6, GPIO7, GPIO8, GPIO9 */
+#define BOARD_BOOTCLOCKRUN_CAN_CLK_ROOT 40000000UL /* Clock consumers of CAN_CLK_ROOT output : CAN1, CAN2, CAN3 */
+#define BOARD_BOOTCLOCKRUN_CKIL_SYNC_CLK_ROOT 32768UL /* Clock consumers of CKIL_SYNC_CLK_ROOT output : CSU, EWM, GPT1, GPT2, KPP, PIT, RTWDOG, SNVS, SPDIF, TEMPMON, TSC, USB1, USB2, WDOG1, WDOG2 */
+#define BOARD_BOOTCLOCKRUN_CLKO1_CLK 0UL /* Clock consumers of CLKO1_CLK output : N/A */
+#define BOARD_BOOTCLOCKRUN_CLKO2_CLK 0UL /* Clock consumers of CLKO2_CLK output : N/A */
+#define BOARD_BOOTCLOCKRUN_CLK_1M 1000000UL /* Clock consumers of CLK_1M output : EWM, RTWDOG */
+#define BOARD_BOOTCLOCKRUN_CLK_24M 24000000UL /* Clock consumers of CLK_24M output : GPT1, GPT2 */
+#define BOARD_BOOTCLOCKRUN_CSI_CLK_ROOT 12000000UL /* Clock consumers of CSI_CLK_ROOT output : CSI */
+#define BOARD_BOOTCLOCKRUN_ENET2_125M_CLK 1200000UL /* Clock consumers of ENET2_125M_CLK output : N/A */
+#define BOARD_BOOTCLOCKRUN_ENET2_REF_CLK 0UL /* Clock consumers of ENET2_REF_CLK output : ENET2 */
+#define BOARD_BOOTCLOCKRUN_ENET2_TX_CLK 0UL /* Clock consumers of ENET2_TX_CLK output : ENET2 */
+#define BOARD_BOOTCLOCKRUN_ENET_125M_CLK 2400000UL /* Clock consumers of ENET_125M_CLK output : N/A */
+#define BOARD_BOOTCLOCKRUN_ENET_25M_REF_CLK 1200000UL /* Clock consumers of ENET_25M_REF_CLK output : ENET, ENET2 */
+#define BOARD_BOOTCLOCKRUN_ENET_REF_CLK 0UL /* Clock consumers of ENET_REF_CLK output : ENET */
+#define BOARD_BOOTCLOCKRUN_ENET_TX_CLK 0UL /* Clock consumers of ENET_TX_CLK output : ENET */
+#define BOARD_BOOTCLOCKRUN_FLEXIO1_CLK_ROOT 30000000UL /* Clock consumers of FLEXIO1_CLK_ROOT output : FLEXIO1 */
+#define BOARD_BOOTCLOCKRUN_FLEXIO2_CLK_ROOT 30000000UL /* Clock consumers of FLEXIO2_CLK_ROOT output : FLEXIO2, FLEXIO3 */
+#define BOARD_BOOTCLOCKRUN_FLEXSPI2_CLK_ROOT 130909090UL /* Clock consumers of FLEXSPI2_CLK_ROOT output : FLEXSPI2 */
+#define BOARD_BOOTCLOCKRUN_FLEXSPI_CLK_ROOT 130909090UL /* Clock consumers of FLEXSPI_CLK_ROOT output : FLEXSPI */
+#define BOARD_BOOTCLOCKRUN_GPT1_IPG_CLK_HIGHFREQ 75000000UL /* Clock consumers of GPT1_ipg_clk_highfreq output : GPT1 */
+#define BOARD_BOOTCLOCKRUN_GPT2_IPG_CLK_HIGHFREQ 75000000UL /* Clock consumers of GPT2_ipg_clk_highfreq output : GPT2 */
+#define BOARD_BOOTCLOCKRUN_IPG_CLK_ROOT 150000000UL /* Clock consumers of IPG_CLK_ROOT output : ADC1, ADC2, ADC_ETC, AOI1, AOI2, ARM, BEE, CAN1, CAN2, CAN3, CCM, CMP1, CMP2, CMP3, CMP4, CSI, CSU, DCDC, DCP, DMA0, DMAMUX, ENC1, ENC2, ENC3, ENC4, ENET, ENET2, EWM, FLEXIO1, FLEXIO2, FLEXIO3, FLEXRAM, FLEXSPI, FLEXSPI2, GPC, GPIO1, GPIO10, GPIO2, GPIO3, GPIO4, GPIO5, IOMUXC, KPP, LCDIF, LPI2C1, LPI2C2, LPI2C3, LPI2C4, LPSPI1, LPSPI2, LPSPI3, LPSPI4, LPUART1, LPUART2, LPUART3, LPUART4, LPUART5, LPUART6, LPUART7, LPUART8, NVIC, OCOTP, PMU, PWM1, PWM2, PWM3, PWM4, PXP, ROMC, RTWDOG, SAI1, SAI2, SAI3, SNVS, SPDIF, SRC, TEMPMON, TMR1, TMR2, TMR3, TMR4, TRNG, TSC, USB1, USB2, USDHC1, USDHC2, WDOG1, WDOG2, XBARA1, XBARB2, XBARB3 */
+#define BOARD_BOOTCLOCKRUN_LCDIF_CLK_ROOT 67500000UL /* Clock consumers of LCDIF_CLK_ROOT output : LCDIF */
+#define BOARD_BOOTCLOCKRUN_LPI2C_CLK_ROOT 60000000UL /* Clock consumers of LPI2C_CLK_ROOT output : LPI2C1, LPI2C2, LPI2C3, LPI2C4 */
+#define BOARD_BOOTCLOCKRUN_LPSPI_CLK_ROOT 105600000UL /* Clock consumers of LPSPI_CLK_ROOT output : LPSPI1, LPSPI2, LPSPI3, LPSPI4 */
+#define BOARD_BOOTCLOCKRUN_LVDS1_CLK 1200000000UL /* Clock consumers of LVDS1_CLK output : N/A */
+#define BOARD_BOOTCLOCKRUN_MQS_MCLK 63529411UL /* Clock consumers of MQS_MCLK output : N/A */
+#define BOARD_BOOTCLOCKRUN_PERCLK_CLK_ROOT 75000000UL /* Clock consumers of PERCLK_CLK_ROOT output : GPT1, GPT2, PIT */
+#define BOARD_BOOTCLOCKRUN_PLL7_MAIN_CLK 480000000UL /* Clock consumers of PLL7_MAIN_CLK output : N/A */
+#define BOARD_BOOTCLOCKRUN_SAI1_CLK_ROOT 63529411UL /* Clock consumers of SAI1_CLK_ROOT output : N/A */
+#define BOARD_BOOTCLOCKRUN_SAI1_MCLK1 63529411UL /* Clock consumers of SAI1_MCLK1 output : SAI1 */
+#define BOARD_BOOTCLOCKRUN_SAI1_MCLK2 63529411UL /* Clock consumers of SAI1_MCLK2 output : SAI1 */
+#define BOARD_BOOTCLOCKRUN_SAI1_MCLK3 30000000UL /* Clock consumers of SAI1_MCLK3 output : SAI1 */
+#define BOARD_BOOTCLOCKRUN_SAI2_CLK_ROOT 63529411UL /* Clock consumers of SAI2_CLK_ROOT output : N/A */
+#define BOARD_BOOTCLOCKRUN_SAI2_MCLK1 63529411UL /* Clock consumers of SAI2_MCLK1 output : SAI2 */
+#define BOARD_BOOTCLOCKRUN_SAI2_MCLK2 0UL /* Clock consumers of SAI2_MCLK2 output : SAI2 */
+#define BOARD_BOOTCLOCKRUN_SAI2_MCLK3 30000000UL /* Clock consumers of SAI2_MCLK3 output : SAI2 */
+#define BOARD_BOOTCLOCKRUN_SAI3_CLK_ROOT 63529411UL /* Clock consumers of SAI3_CLK_ROOT output : N/A */
+#define BOARD_BOOTCLOCKRUN_SAI3_MCLK1 63529411UL /* Clock consumers of SAI3_MCLK1 output : SAI3 */
+#define BOARD_BOOTCLOCKRUN_SAI3_MCLK2 0UL /* Clock consumers of SAI3_MCLK2 output : SAI3 */
+#define BOARD_BOOTCLOCKRUN_SAI3_MCLK3 30000000UL /* Clock consumers of SAI3_MCLK3 output : SAI3 */
+#define BOARD_BOOTCLOCKRUN_SEMC_CLK_ROOT 75000000UL /* Clock consumers of SEMC_CLK_ROOT output : SEMC */
+#define BOARD_BOOTCLOCKRUN_SPDIF0_CLK_ROOT 30000000UL /* Clock consumers of SPDIF0_CLK_ROOT output : SPDIF */
+#define BOARD_BOOTCLOCKRUN_SPDIF0_EXTCLK_OUT 0UL /* Clock consumers of SPDIF0_EXTCLK_OUT output : SPDIF */
+#define BOARD_BOOTCLOCKRUN_TRACE_CLK_ROOT 132000000UL /* Clock consumers of TRACE_CLK_ROOT output : ARM */
+#define BOARD_BOOTCLOCKRUN_UART_CLK_ROOT 80000000UL /* Clock consumers of UART_CLK_ROOT output : LPUART1, LPUART2, LPUART3, LPUART4, LPUART5, LPUART6, LPUART7, LPUART8 */
+#define BOARD_BOOTCLOCKRUN_USBPHY1_CLK 480000000UL /* Clock consumers of USBPHY1_CLK output : TEMPMON, USB1 */
+#define BOARD_BOOTCLOCKRUN_USBPHY2_CLK 480000000UL /* Clock consumers of USBPHY2_CLK output : USB2 */
+#define BOARD_BOOTCLOCKRUN_USDHC1_CLK_ROOT 198000000UL /* Clock consumers of USDHC1_CLK_ROOT output : USDHC1 */
+#define BOARD_BOOTCLOCKRUN_USDHC2_CLK_ROOT 198000000UL /* Clock consumers of USDHC2_CLK_ROOT output : USDHC2 */
/*! @brief Arm PLL set for BOARD_BootClockRUN configuration.
*/
diff --git a/hw/bsp/imxrt/boards/mimxrt1064_evk/board/pin_mux.c b/hw/bsp/imxrt/boards/mimxrt1064_evk/board/pin_mux.c
index 8e975dc72..60c4bab37 100644
--- a/hw/bsp/imxrt/boards/mimxrt1064_evk/board/pin_mux.c
+++ b/hw/bsp/imxrt/boards/mimxrt1064_evk/board/pin_mux.c
@@ -6,11 +6,11 @@
/*
* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
!!GlobalInfo
-product: Pins v13.1
+product: Pins v17.0
processor: MIMXRT1064xxxxA
package_id: MIMXRT1064DVL6A
mcu_data: ksdk2_0
-processor_version: 13.0.2
+processor_version: 24.12.10
board: MIMXRT1064-EVK
pin_labels:
- {pin_num: F14, pin_signal: GPIO_AD_B0_09, label: 'JTAG_TDI/J21[5]/ENET_RST/J22[5]', identifier: USER_LED}
@@ -81,7 +81,6 @@ void BOARD_InitPins(void) {
IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_09_GPIO1_IO09, 0x50A0U);
}
-
/*
* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
BOARD_InitDEBUG_UARTPins:
@@ -109,7 +108,6 @@ void BOARD_InitDEBUG_UARTPins(void) {
IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B0_13_LPUART1_RX, 0x10B0U);
}
-
/*
* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
BOARD_InitSDRAMPins:
@@ -209,7 +207,6 @@ void BOARD_InitSDRAMPins(void) {
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_39_SEMC_DQS, 0U);
}
-
/*
* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
BOARD_InitCSIPins:
@@ -267,7 +264,6 @@ void BOARD_InitCSIPins(void) {
IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B1_01_LPI2C1_SDA, 0xD8B0U);
}
-
/*
* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
BOARD_InitLCDPins:
@@ -360,7 +356,6 @@ void BOARD_InitLCDPins(void) {
IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_15_GPIO2_IO31, 0x10B0U);
}
-
/*
* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
BOARD_InitCANPins:
@@ -384,7 +379,6 @@ void BOARD_InitCANPins(void) {
IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_15_FLEXCAN2_RX, 0U);
}
-
/*
* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
BOARD_InitENETPins:
@@ -424,7 +418,6 @@ void BOARD_InitENETPins(void) {
IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_41_ENET_MDIO, 0U);
}
-
/*
* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
BOARD_InitUSDHCPins:
@@ -458,7 +451,6 @@ void BOARD_InitUSDHCPins(void) {
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B0_05_USDHC1_DATA3, 0U);
}
-
/*
* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
BOARD_InitQSPIPins:
@@ -491,7 +483,6 @@ void BOARD_InitQSPIPins(void) {
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_10_FLEXSPIA_DATA02, 0U);
IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_11_FLEXSPIA_DATA03, 0U);
}
-
/***********************************************************************************************************************
* EOF
**********************************************************************************************************************/
diff --git a/hw/bsp/imxrt/boards/mimxrt1064_evk/board/pin_mux.h b/hw/bsp/imxrt/boards/mimxrt1064_evk/board/pin_mux.h
index bf494b6f6..be1461f16 100644
--- a/hw/bsp/imxrt/boards/mimxrt1064_evk/board/pin_mux.h
+++ b/hw/bsp/imxrt/boards/mimxrt1064_evk/board/pin_mux.h
@@ -47,6 +47,7 @@ void BOARD_InitBootPins(void);
/* Symbols to be used with GPIO driver */
#define BOARD_INITPINS_USER_LED_GPIO GPIO1 /*!< GPIO peripheral base pointer */
+#define BOARD_INITPINS_USER_LED_INIT_GPIO_VALUE 0U /*!< GPIO output initial state */
#define BOARD_INITPINS_USER_LED_GPIO_PIN 9U /*!< GPIO pin number */
#define BOARD_INITPINS_USER_LED_GPIO_PIN_MASK (1U << 9U) /*!< GPIO pin mask */
#define BOARD_INITPINS_USER_LED_PORT GPIO1 /*!< PORT peripheral base pointer */
diff --git a/hw/bsp/imxrt/boards/mimxrt1064_evk/mimxrt1064_evk.mex b/hw/bsp/imxrt/boards/mimxrt1064_evk/mimxrt1064_evk.mex
index 3f0948101..58247fa5b 100644
--- a/hw/bsp/imxrt/boards/mimxrt1064_evk/mimxrt1064_evk.mex
+++ b/hw/bsp/imxrt/boards/mimxrt1064_evk/mimxrt1064_evk.mex
@@ -1,5 +1,5 @@
-
+
MIMXRT1064xxxxA
MIMXRT1064DVL6A
@@ -13,19 +13,18 @@
true
- false
false
true
false
-
+
- 13.0.2
+ 24.12.10
@@ -41,7 +40,7 @@
true
-
+
true
@@ -84,7 +83,7 @@
true
-
+
true
@@ -137,7 +136,7 @@
true
-
+
true
@@ -204,12 +203,12 @@
true
-
+
true
-
+
true
@@ -277,7 +276,7 @@
true
-
+
true
@@ -450,7 +449,7 @@
true
-
+
true
@@ -479,7 +478,7 @@
true
-
+
true
@@ -516,7 +515,7 @@
true
-
+
true
@@ -550,7 +549,7 @@
true
-
+
true
@@ -578,13 +577,13 @@
-
+
- 13.0.2
+ 24.12.10
@@ -751,10 +750,7 @@
-
-
-
-
+
13.0.2
diff --git a/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/clock_config.c b/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/clock_config.c
index 66f1f983a..4f06299de 100644
--- a/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/clock_config.c
+++ b/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/clock_config.c
@@ -11,11 +11,11 @@
/* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
!!GlobalInfo
-product: Clocks v14.0
+product: Clocks v15.0
processor: MIMXRT1176xxxxx
package_id: MIMXRT1176DVMAA
mcu_data: ksdk2_0
-processor_version: 16.3.0
+processor_version: 24.12.10
board: MIMXRT1170-EVKB
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS **********/
diff --git a/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/pin_mux.c b/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/pin_mux.c
index 2c83fb55e..5e8cb91c1 100644
--- a/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/pin_mux.c
+++ b/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/pin_mux.c
@@ -6,11 +6,11 @@
/*
* TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
!!GlobalInfo
-product: Pins v16.0
+product: Pins v17.0
processor: MIMXRT1176xxxxx
package_id: MIMXRT1176DVMAA
mcu_data: ksdk2_0
-processor_version: 16.3.0
+processor_version: 24.12.10
board: MIMXRT1170-EVKB
external_user_signals: {}
pin_labels:
@@ -31,6 +31,7 @@ pin_labels:
* END ****************************************************************************************************************/
void BOARD_InitBootPins(void) {
BOARD_InitPins();
+ BOARD_InitDEBUG_UARTPins();
}
/*
@@ -38,10 +39,6 @@ void BOARD_InitBootPins(void) {
BOARD_InitPins:
- options: {callFromInitBoot: 'true', coreID: cm7, enableClock: 'true'}
- pin_list:
- - {pin_num: M15, peripheral: LPUART1, signal: RXD, pin_signal: GPIO_AD_25, software_input_on: Disable, pull_up_down_config: Pull_Down, pull_keeper_select: Keeper,
- open_drain: Disable, drive_strength: High, slew_rate: Slow}
- - {pin_num: L13, peripheral: LPUART1, signal: TXD, pin_signal: GPIO_AD_24, software_input_on: Disable, pull_up_down_config: Pull_Down, pull_keeper_select: Keeper,
- open_drain: Disable, drive_strength: High, slew_rate: Slow}
- {pin_num: M13, peripheral: GPIO9, signal: 'gpio_io, 03', pin_signal: GPIO_AD_04, identifier: USER_LED, direction: OUTPUT, pull_up_down_config: Pull_Down, pull_keeper_select: Keeper}
- {pin_num: T8, peripheral: GPIO13, signal: 'gpio_io, 00', pin_signal: WAKEUP, direction: INPUT, pull_up_down_config: Pull_Up}
* BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS ***********
@@ -77,12 +74,6 @@ void BOARD_InitPins(void) {
IOMUXC_SetPinMux(
IOMUXC_GPIO_AD_04_GPIO9_IO03, /* GPIO_AD_04 is configured as GPIO9_IO03 */
0U); /* Software Input On Field: Input Path is determined by functionality */
- IOMUXC_SetPinMux(
- IOMUXC_GPIO_AD_24_LPUART1_TXD, /* GPIO_AD_24 is configured as LPUART1_TXD */
- 0U); /* Software Input On Field: Input Path is determined by functionality */
- IOMUXC_SetPinMux(
- IOMUXC_GPIO_AD_25_LPUART1_RXD, /* GPIO_AD_25 is configured as LPUART1_RXD */
- 0U); /* Software Input On Field: Input Path is determined by functionality */
IOMUXC_SetPinMux(
IOMUXC_WAKEUP_DIG_GPIO13_IO00, /* WAKEUP_DIG is configured as GPIO13_IO00 */
0U); /* Software Input On Field: Input Path is determined by functionality */
@@ -95,6 +86,40 @@ void BOARD_InitPins(void) {
Open Drain Field: Disabled
Domain write protection: Both cores are allowed
Domain write protection lock: Neither of DWP bits is locked */
+ IOMUXC_SetPinConfig(
+ IOMUXC_WAKEUP_DIG_GPIO13_IO00, /* WAKEUP_DIG PAD functional properties : */
+ 0x0EU); /* Pull / Keep Select Field: Pull Enable
+ Pull Up / Down Config. Field: Weak pull up
+ Open Drain SNVS Field: Disabled
+ Domain write protection: Both cores are allowed
+ Domain write protection lock: Neither of DWP bits is locked */
+}
+
+/*
+ * TEXT BELOW IS USED AS SETTING FOR TOOLS *************************************
+BOARD_InitDEBUG_UARTPins:
+- options: {callFromInitBoot: 'true', coreID: cm7, enableClock: 'true'}
+- pin_list:
+ - {pin_num: L13, peripheral: LPUART1, signal: TXD, pin_signal: GPIO_AD_24, pull_keeper_select: Keeper, slew_rate: Slow}
+ - {pin_num: M15, peripheral: LPUART1, signal: RXD, pin_signal: GPIO_AD_25, pull_keeper_select: Keeper, slew_rate: Slow}
+ * BE CAREFUL MODIFYING THIS COMMENT - IT IS YAML SETTINGS FOR TOOLS ***********
+ */
+
+/* FUNCTION ************************************************************************************************************
+ *
+ * Function Name : BOARD_InitDEBUG_UARTPins, assigned for the Cortex-M7F core.
+ * Description : Configures pin routing and optionally pin electrical features.
+ *
+ * END ****************************************************************************************************************/
+void BOARD_InitDEBUG_UARTPins(void) {
+ CLOCK_EnableClock(kCLOCK_Iomuxc); /* LPCG on: LPCG is ON. */
+
+ IOMUXC_SetPinMux(
+ IOMUXC_GPIO_AD_24_LPUART1_TXD, /* GPIO_AD_24 is configured as LPUART1_TXD */
+ 0U); /* Software Input On Field: Input Path is determined by functionality */
+ IOMUXC_SetPinMux(
+ IOMUXC_GPIO_AD_25_LPUART1_RXD, /* GPIO_AD_25 is configured as LPUART1_RXD */
+ 0U); /* Software Input On Field: Input Path is determined by functionality */
IOMUXC_SetPinConfig(
IOMUXC_GPIO_AD_24_LPUART1_TXD, /* GPIO_AD_24 PAD functional properties : */
0x02U); /* Slew Rate Field: Slow Slew Rate
@@ -113,13 +138,6 @@ void BOARD_InitPins(void) {
Open Drain Field: Disabled
Domain write protection: Both cores are allowed
Domain write protection lock: Neither of DWP bits is locked */
- IOMUXC_SetPinConfig(
- IOMUXC_WAKEUP_DIG_GPIO13_IO00, /* WAKEUP_DIG PAD functional properties : */
- 0x0EU); /* Pull / Keep Select Field: Pull Enable
- Pull Up / Down Config. Field: Weak pull up
- Open Drain SNVS Field: Disabled
- Domain write protection: Both cores are allowed
- Domain write protection lock: Neither of DWP bits is locked */
}
/***********************************************************************************************************************
* EOF
diff --git a/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/pin_mux.h b/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/pin_mux.h
index a5b621476..0e0368ef6 100644
--- a/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/pin_mux.h
+++ b/hw/bsp/imxrt/boards/mimxrt1170_evkb/board/pin_mux.h
@@ -25,16 +25,6 @@ extern "C" {
*/
void BOARD_InitBootPins(void);
-/* GPIO_AD_25 (coord M15), LPUART1_RXD */
-/* Routed pin properties */
-#define BOARD_INITPINS_LPUART1_RXD_PERIPHERAL LPUART1 /*!< Peripheral name */
-#define BOARD_INITPINS_LPUART1_RXD_SIGNAL RXD /*!< Signal name */
-
-/* GPIO_AD_24 (coord L13), LPUART1_TXD */
-/* Routed pin properties */
-#define BOARD_INITPINS_LPUART1_TXD_PERIPHERAL LPUART1 /*!< Peripheral name */
-#define BOARD_INITPINS_LPUART1_TXD_SIGNAL TXD /*!< Signal name */
-
/* GPIO_AD_04 (coord M13), SIM1_PD/J44[C8]/USER_LED_CTL1/J9[8]/J25[7] */
/* Routed pin properties */
#define BOARD_INITPINS_USER_LED_PERIPHERAL GPIO9 /*!< Peripheral name */
@@ -43,6 +33,7 @@ void BOARD_InitBootPins(void);
/* Symbols to be used with GPIO driver */
#define BOARD_INITPINS_USER_LED_GPIO GPIO9 /*!< GPIO peripheral base pointer */
+#define BOARD_INITPINS_USER_LED_INIT_GPIO_VALUE 0U /*!< GPIO output initial state */
#define BOARD_INITPINS_USER_LED_GPIO_PIN 3U /*!< GPIO pin number */
#define BOARD_INITPINS_USER_LED_GPIO_PIN_MASK (1U << 3U) /*!< GPIO pin mask */
@@ -63,6 +54,22 @@ void BOARD_InitBootPins(void);
*/
void BOARD_InitPins(void); /* Function assigned for the Cortex-M7F */
+/* GPIO_AD_24 (coord L13), LPUART1_TXD */
+/* Routed pin properties */
+#define BOARD_INITDEBUG_UARTPINS_LPUART1_TXD_PERIPHERAL LPUART1 /*!< Peripheral name */
+#define BOARD_INITDEBUG_UARTPINS_LPUART1_TXD_SIGNAL TXD /*!< Signal name */
+
+/* GPIO_AD_25 (coord M15), LPUART1_RXD */
+/* Routed pin properties */
+#define BOARD_INITDEBUG_UARTPINS_LPUART1_RXD_PERIPHERAL LPUART1 /*!< Peripheral name */
+#define BOARD_INITDEBUG_UARTPINS_LPUART1_RXD_SIGNAL RXD /*!< Signal name */
+
+/*!
+ * @brief Configures pin routing and optionally pin electrical features.
+ *
+ */
+void BOARD_InitDEBUG_UARTPins(void); /* Function assigned for the Cortex-M7F */
+
#if defined(__cplusplus)
}
#endif
diff --git a/hw/bsp/imxrt/boards/mimxrt1170_evkb/mimxrt1170_evkb.mex b/hw/bsp/imxrt/boards/mimxrt1170_evkb/mimxrt1170_evkb.mex
index a4c8917f7..de6b12394 100644
--- a/hw/bsp/imxrt/boards/mimxrt1170_evkb/mimxrt1170_evkb.mex
+++ b/hw/bsp/imxrt/boards/mimxrt1170_evkb/mimxrt1170_evkb.mex
@@ -1,5 +1,5 @@
-
+
MIMXRT1176xxxxx
MIMXRT1176DVMAA
@@ -13,19 +13,18 @@
true
- false
false
true
false
-
+
- 16.3.0
+ 24.12.10
@@ -43,11 +42,6 @@
true
-
-
- true
-
-
true
@@ -65,26 +59,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
@@ -101,15 +75,54 @@
+
+ Configures pin routing and optionally pin electrical features.
+
+ true
+ cm7
+ true
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
- 16.3.0
+ 24.12.10
diff --git a/hw/bsp/imxrt/family.c b/hw/bsp/imxrt/family.c
index ad529a227..7e4734a66 100644
--- a/hw/bsp/imxrt/family.c
+++ b/hw/bsp/imxrt/family.c
@@ -61,7 +61,7 @@
- Define CFG_TUSB_MEM_SECTION=__attribute__((section("NonCacheable")))
*/
-static void BOARD_ConfigMPU(void);
+// static void BOARD_ConfigMPU(void);
// needed by fsl_flexspi_nor_boot
TU_ATTR_USED const uint8_t dcd_data[] = {0x00};
@@ -109,8 +109,8 @@ static void init_usb_phy(uint8_t usb_id) {
}
void board_init(void) {
- BOARD_ConfigMPU();
- BOARD_InitPins();
+ // BOARD_ConfigMPU();
+ BOARD_InitBootPins();
BOARD_BootClockRUN();
SystemCoreClockUpdate();
@@ -258,6 +258,7 @@ void _exit(int __status) {
//--------------------------------------------------------------------
// MPU configuration
//--------------------------------------------------------------------
+#if 0 // TODO move to per board specific
#if __CORTEX_M == 7
static void BOARD_ConfigMPU(void) {
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
@@ -455,7 +456,7 @@ static void BOARD_ConfigMPU(void) {
#elif __CORTEX_M == 4
-void BOARD_ConfigMPU(void) {
+static void BOARD_ConfigMPU(void) {
#if defined(__CC_ARM) || defined(__ARMCC_VERSION)
extern uint32_t Image$$RW_m_ncache$$Base[];
/* RW_m_ncache_unused is a auxiliary region which is used to get the whole size of noncache section */
@@ -636,3 +637,4 @@ void BOARD_ConfigMPU(void) {
LMEM->PCCCR |= LMEM_PCCCR_ENCACHE_MASK;
}
#endif
+#endif
diff --git a/hw/bsp/imxrt/family.cmake b/hw/bsp/imxrt/family.cmake
index f08ccb3e5..6224b63a4 100644
--- a/hw/bsp/imxrt/family.cmake
+++ b/hw/bsp/imxrt/family.cmake
@@ -123,8 +123,6 @@ function(family_configure_example TARGET RTOS)
# Board target
add_board_target(board_${BOARD})
- #---------- Port Specific ----------
- # These files are built for each example since it depends on example's tusb_config.h
target_sources(${TARGET} PUBLIC
# BSP
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
@@ -146,8 +144,6 @@ function(family_configure_example TARGET RTOS)
)
target_link_libraries(${TARGET} PUBLIC board_${BOARD})
-
-
# Flashing
family_add_bin_hex(${TARGET})
family_flash_jlink(${TARGET})
diff --git a/hw/bsp/rp2040/boards/adafruit_feather_rp2040_usb_host/board.cmake b/hw/bsp/rp2040/boards/adafruit_feather_rp2040_usb_host/board.cmake
new file mode 100644
index 000000000..41897f644
--- /dev/null
+++ b/hw/bsp/rp2040/boards/adafruit_feather_rp2040_usb_host/board.cmake
@@ -0,0 +1,2 @@
+set(PICO_PLATFORM rp2040)
+set(PICO_BOARD adafruit_feather_rp2040_usb_host)
diff --git a/hw/bsp/rp2040/boards/adafruit_feather_rp2040_usb_host/board.h b/hw/bsp/rp2040/boards/adafruit_feather_rp2040_usb_host/board.h
new file mode 100644
index 000000000..d003ae828
--- /dev/null
+++ b/hw/bsp/rp2040/boards/adafruit_feather_rp2040_usb_host/board.h
@@ -0,0 +1,69 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2025 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.
+ */
+
+/* metadata:
+ name: Adafruit Feather RP2040 with USB Type A Host
+ url: https://www.adafruit.com/product/5723
+*/
+
+#ifndef TUSB_BOARD_H
+#define TUSB_BOARD_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// UART and LED are already defined in pico-sdk board
+
+//--------------------------------------------------------------------+
+// PIO_USB
+//--------------------------------------------------------------------+
+
+#define PICO_DEFAULT_PIO_USB_DP_PIN 16
+#define PICO_DEFAULT_PIO_USB_VBUSEN_PIN 18
+#define PICO_DEFAULT_PIO_USB_VBUSEN_STATE 1
+
+//--------------------------------------------------------------------
+// USB Host MAX3421E
+//--------------------------------------------------------------------
+
+#ifdef PICO_DEFAULT_SPI
+#define MAX3421_SPI PICO_DEFAULT_SPI // sdk v2
+#else
+#define MAX3421_SPI PICO_DEFAULT_SPI_INSTANCE // sdk v1
+#endif
+
+#define MAX3421_SCK_PIN PICO_DEFAULT_SPI_SCK_PIN
+#define MAX3421_MOSI_PIN PICO_DEFAULT_SPI_TX_PIN
+#define MAX3421_MISO_PIN PICO_DEFAULT_SPI_RX_PIN
+#define MAX3421_CS_PIN 10
+#define MAX3421_INTR_PIN 9
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/hw/bsp/rp2040/boards/adafruit_fruit_jam/adafruit_fruit_jam.h b/hw/bsp/rp2040/boards/adafruit_fruit_jam/adafruit_fruit_jam.h
new file mode 100644
index 000000000..2d4c689de
--- /dev/null
+++ b/hw/bsp/rp2040/boards/adafruit_fruit_jam/adafruit_fruit_jam.h
@@ -0,0 +1,113 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2025 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 BOARDS_ADAFRUIT_FRUIT_JAM_H
+#define BOARDS_ADAFRUIT_FRUIT_JAM_H
+
+// required for board that is not part of pico-sdk
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+
+// pico_cmake_set PICO_PLATFORM=rp2350
+
+// On some samples, the xosc can take longer to stabilize than is usual
+#ifndef PICO_XOSC_STARTUP_DELAY_MULTIPLIER
+#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64
+#endif
+
+// For board detection
+#define ADAFRUIT_FRUIT_JAM
+
+// --- RP2350 VARIANT ---
+#define PICO_RP2350A 0
+
+// --- UART ---
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 1
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 8
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 9
+#endif
+
+// --- LED ---
+#ifndef PICO_DEFAULT_LED_PIN
+#define PICO_DEFAULT_LED_PIN 29
+#endif
+
+#ifndef PICO_DEFAULT_WS2812_PIN
+#define PICO_DEFAULT_WS2812_PIN 32
+#endif
+
+// --- I2C ---
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 20
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 21
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 1
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 30
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 31
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 28
+#endif
+
+// --- FLASH ---
+
+// FruitJam use w25q128 but sdk does not have .s for it, use q080 instead
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (8 * 1024 * 1024)
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
+#endif
+
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
+#ifndef PICO_RP2350_A2_SUPPORTED
+#define PICO_RP2350_A2_SUPPORTED 1
+#endif
+
+#endif
diff --git a/hw/bsp/rp2040/boards/adafruit_fruit_jam/board.cmake b/hw/bsp/rp2040/boards/adafruit_fruit_jam/board.cmake
new file mode 100644
index 000000000..4ab8a5477
--- /dev/null
+++ b/hw/bsp/rp2040/boards/adafruit_fruit_jam/board.cmake
@@ -0,0 +1,4 @@
+set(PICO_PLATFORM rp2350-arm-s)
+set(PICO_BOARD adafruit_fruit_jam)
+set(PICO_BOARD_HEADER_DIRS ${CMAKE_CURRENT_LIST_DIR})
+#set(OPENOCD_SERIAL E6614103E78E8324)
diff --git a/hw/bsp/rp2040/boards/adafruit_fruit_jam/board.h b/hw/bsp/rp2040/boards/adafruit_fruit_jam/board.h
new file mode 100644
index 000000000..0f53fd96f
--- /dev/null
+++ b/hw/bsp/rp2040/boards/adafruit_fruit_jam/board.h
@@ -0,0 +1,57 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2025 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.
+ */
+
+/* metadata:
+ name: Adafruit Fruit Jam - Mini RP2350
+ url: https://www.adafruit.com/product/6200
+*/
+
+#ifndef TUSB_BOARD_H
+#define TUSB_BOARD_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// UART and LED are already defined in pico-sdk board
+
+//--------------------------------------------------------------------+
+// PIO_USB
+//--------------------------------------------------------------------+
+// default to pico brain tester
+#define PICO_DEFAULT_PIO_USB_DP_PIN 1
+#define PICO_DEFAULT_PIO_USB_VBUSEN_PIN 11
+#define PICO_DEFAULT_PIO_USB_VBUSEN_STATE 1
+
+//--------------------------------------------------------------------
+// USB Host MAX3421E
+//--------------------------------------------------------------------
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/hw/bsp/rp2040/boards/adafruit_metro_rp2350/adafruit_metro_rp2350.h b/hw/bsp/rp2040/boards/adafruit_metro_rp2350/adafruit_metro_rp2350.h
new file mode 100644
index 000000000..9fb9658a5
--- /dev/null
+++ b/hw/bsp/rp2040/boards/adafruit_metro_rp2350/adafruit_metro_rp2350.h
@@ -0,0 +1,113 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2025 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 BOARDS_ADAFRUIT_METRO_RP2350_H
+#define BOARDS_ADAFRUIT_METRO_RP2350_H
+
+// required for board that is not part of pico-sdk
+
+// -----------------------------------------------------
+// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
+// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
+// -----------------------------------------------------
+
+// pico_cmake_set PICO_PLATFORM=rp2350
+
+// On some samples, the xosc can take longer to stabilize than is usual
+#ifndef PICO_XOSC_STARTUP_DELAY_MULTIPLIER
+#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64
+#endif
+
+// For board detection
+#define ADAFRUIT_METRO_RP2350
+
+// --- RP2350 VARIANT ---
+#define PICO_RP2350A 0
+
+// --- UART ---
+#ifndef PICO_DEFAULT_UART
+#define PICO_DEFAULT_UART 0
+#endif
+#ifndef PICO_DEFAULT_UART_TX_PIN
+#define PICO_DEFAULT_UART_TX_PIN 0
+#endif
+#ifndef PICO_DEFAULT_UART_RX_PIN
+#define PICO_DEFAULT_UART_RX_PIN 1
+#endif
+
+// --- LED ---
+#ifndef PICO_DEFAULT_LED_PIN
+#define PICO_DEFAULT_LED_PIN 23
+#endif
+
+#ifndef PICO_DEFAULT_WS2812_PIN
+#define PICO_DEFAULT_WS2812_PIN 25
+#endif
+
+// --- I2C ---
+#ifndef PICO_DEFAULT_I2C
+#define PICO_DEFAULT_I2C 0
+#endif
+#ifndef PICO_DEFAULT_I2C_SDA_PIN
+#define PICO_DEFAULT_I2C_SDA_PIN 20
+#endif
+#ifndef PICO_DEFAULT_I2C_SCL_PIN
+#define PICO_DEFAULT_I2C_SCL_PIN 21
+#endif
+
+// --- SPI ---
+#ifndef PICO_DEFAULT_SPI
+#define PICO_DEFAULT_SPI 1
+#endif
+#ifndef PICO_DEFAULT_SPI_SCK_PIN
+#define PICO_DEFAULT_SPI_SCK_PIN 30
+#endif
+#ifndef PICO_DEFAULT_SPI_TX_PIN
+#define PICO_DEFAULT_SPI_TX_PIN 31
+#endif
+#ifndef PICO_DEFAULT_SPI_RX_PIN
+#define PICO_DEFAULT_SPI_RX_PIN 28
+#endif
+
+// --- FLASH ---
+
+// FruitJam use w25q128 but sdk does not have .s for it, use q080 instead
+#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
+
+#ifndef PICO_FLASH_SPI_CLKDIV
+#define PICO_FLASH_SPI_CLKDIV 2
+#endif
+
+// pico_cmake_set_default PICO_FLASH_SIZE_BYTES = (8 * 1024 * 1024)
+#ifndef PICO_FLASH_SIZE_BYTES
+#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
+#endif
+
+// pico_cmake_set_default PICO_RP2350_A2_SUPPORTED = 1
+#ifndef PICO_RP2350_A2_SUPPORTED
+#define PICO_RP2350_A2_SUPPORTED 1
+#endif
+
+#endif
diff --git a/hw/bsp/rp2040/boards/adafruit_metro_rp2350/board.cmake b/hw/bsp/rp2040/boards/adafruit_metro_rp2350/board.cmake
new file mode 100644
index 000000000..9a58821a5
--- /dev/null
+++ b/hw/bsp/rp2040/boards/adafruit_metro_rp2350/board.cmake
@@ -0,0 +1,4 @@
+set(PICO_PLATFORM rp2350-arm-s)
+set(PICO_BOARD adafruit_metro_rp2350)
+set(PICO_BOARD_HEADER_DIRS ${CMAKE_CURRENT_LIST_DIR})
+#set(OPENOCD_SERIAL E6614103E78E8324)
diff --git a/hw/bsp/rp2040/boards/adafruit_metro_rp2350/board.h b/hw/bsp/rp2040/boards/adafruit_metro_rp2350/board.h
new file mode 100644
index 000000000..0b8515d1f
--- /dev/null
+++ b/hw/bsp/rp2040/boards/adafruit_metro_rp2350/board.h
@@ -0,0 +1,57 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2025 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.
+ */
+
+/* metadata:
+ name: Adafruit Metro RP2350
+ url: https://www.adafruit.com/product/6003
+*/
+
+#ifndef TUSB_BOARD_H
+#define TUSB_BOARD_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// UART and LED are already defined in pico-sdk board
+
+//--------------------------------------------------------------------+
+// PIO_USB
+//--------------------------------------------------------------------+
+// default to pico brain tester
+#define PICO_DEFAULT_PIO_USB_DP_PIN 32
+#define PICO_DEFAULT_PIO_USB_VBUSEN_PIN 29
+#define PICO_DEFAULT_PIO_USB_VBUSEN_STATE 1
+
+//--------------------------------------------------------------------
+// USB Host MAX3421E
+//--------------------------------------------------------------------
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/hw/bsp/rp2040/boards/feather_rp2040_max3421/board.h b/hw/bsp/rp2040/boards/feather_rp2040_max3421/board.h
new file mode 100644
index 000000000..f36ca14c9
--- /dev/null
+++ b/hw/bsp/rp2040/boards/feather_rp2040_max3421/board.h
@@ -0,0 +1,64 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2025 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 TUSB_BOARD_H
+#define TUSB_BOARD_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// UART and LED are already defined in pico-sdk board
+
+//--------------------------------------------------------------------+
+// PIO_USB
+//--------------------------------------------------------------------+
+
+#define PICO_DEFAULT_PIO_USB_DP_PIN 16
+#define PICO_DEFAULT_PIO_USB_VBUSEN_PIN 18
+#define PICO_DEFAULT_PIO_USB_VBUSEN_STATE 1
+
+//--------------------------------------------------------------------
+// USB Host MAX3421E
+//--------------------------------------------------------------------
+
+#ifdef PICO_DEFAULT_SPI
+#define MAX3421_SPI PICO_DEFAULT_SPI // sdk v2
+#else
+#define MAX3421_SPI PICO_DEFAULT_SPI_INSTANCE // sdk v1
+#endif
+
+#define MAX3421_SCK_PIN PICO_DEFAULT_SPI_SCK_PIN
+#define MAX3421_MOSI_PIN PICO_DEFAULT_SPI_TX_PIN
+#define MAX3421_MISO_PIN PICO_DEFAULT_SPI_RX_PIN
+#define MAX3421_CS_PIN 10
+#define MAX3421_INTR_PIN 9
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/hw/bsp/rp2040/boards/pico_sdk/board.h b/hw/bsp/rp2040/boards/pico_sdk/board.h
new file mode 100644
index 000000000..284edac7d
--- /dev/null
+++ b/hw/bsp/rp2040/boards/pico_sdk/board.h
@@ -0,0 +1,40 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2025 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 TUSB_BOARD_H
+#define TUSB_BOARD_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// UART and LED are already defined in pico-sdk board
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/hw/bsp/rp2040/boards/raspberry_pi_pico/board.cmake b/hw/bsp/rp2040/boards/raspberry_pi_pico/board.cmake
index 804cdb50a..2d739291c 100644
--- a/hw/bsp/rp2040/boards/raspberry_pi_pico/board.cmake
+++ b/hw/bsp/rp2040/boards/raspberry_pi_pico/board.cmake
@@ -1,2 +1,3 @@
set(PICO_PLATFORM rp2040)
set(PICO_BOARD pico)
+#set(OPENOCD_SERIAL E6614103E719612F)
diff --git a/hw/bsp/rp2040/board.h b/hw/bsp/rp2040/boards/raspberry_pi_pico/board.h
similarity index 63%
rename from hw/bsp/rp2040/board.h
rename to hw/bsp/rp2040/boards/raspberry_pi_pico/board.h
index 5dbb1dd37..88f8793f4 100644
--- a/hw/bsp/rp2040/board.h
+++ b/hw/bsp/rp2040/boards/raspberry_pi_pico/board.h
@@ -1,7 +1,7 @@
/*
* The MIT License (MIT)
*
- * Copyright (c) 2021, Ha Thach (tinyusb.org)
+ * Copyright (c) 2025 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
@@ -26,58 +26,25 @@
/* metadata:
name: Pico
- url: https://www.raspberrypi.org/products/raspberry-pi-pico/
+ url: https://www.raspberrypi.com/products/raspberry-pi-pico/
*/
-#ifndef BOARD_H_
-#define BOARD_H_
+#ifndef TUSB_BOARD_H
+#define TUSB_BOARD_H
#ifdef __cplusplus
extern "C" {
#endif
-// LED
-#ifdef PICO_DEFAULT_LED_PIN
-#define LED_PIN PICO_DEFAULT_LED_PIN
-#define LED_STATE_ON (!(PICO_DEFAULT_LED_PIN_INVERTED))
-#endif
-
-// Button pin is BOOTSEL which is flash CS pin
-#define BUTTON_BOOTSEL
-#define BUTTON_STATE_ACTIVE 0
-
-// UART
-#if defined(PICO_DEFAULT_UART_TX_PIN) && defined(PICO_DEFAULT_UART_RX_PIN) && \
- defined(PICO_DEFAULT_UART) && defined(LIB_PICO_STDIO_UART)
-#define UART_DEV PICO_DEFAULT_UART
-#define UART_TX_PIN PICO_DEFAULT_UART_TX_PIN
-#define UART_RX_PIN PICO_DEFAULT_UART_RX_PIN
-#endif
+// UART and LED are already defined in pico-sdk board
//--------------------------------------------------------------------+
// PIO_USB
-// default to pin on Adafruit Feather rp2040 USB Host or Tester if defined
//--------------------------------------------------------------------+
-
-// #define USE_ADAFRUIT_FEATHER_RP2040_USBHOST
-#ifdef USE_ADAFRUIT_FEATHER_RP2040_USBHOST
-#define PICO_DEFAULT_PIO_USB_DP_PIN 16
-#define PICO_DEFAULT_PIO_USB_VBUSEN_PIN 18
-#endif
-
-#ifndef PICO_DEFAULT_PIO_USB_DP_PIN
+// default to pico brain tester
#define PICO_DEFAULT_PIO_USB_DP_PIN 20
-#endif
-
-// VBUS enable pin and its active state
-#ifndef PICO_DEFAULT_PIO_USB_VBUSEN_PIN
#define PICO_DEFAULT_PIO_USB_VBUSEN_PIN 22
-#endif
-
-// VBUS enable state
-#ifndef PICO_DEFAULT_PIO_USB_VBUSEN_STATE
#define PICO_DEFAULT_PIO_USB_VBUSEN_STATE 1
-#endif
//--------------------------------------------------------------------
// USB Host MAX3421E
@@ -99,4 +66,4 @@
}
#endif
-#endif /* BOARD_H_ */
+#endif
diff --git a/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.cmake b/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.cmake
index 3482e2674..0a7dd4d23 100644
--- a/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.cmake
+++ b/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.cmake
@@ -1,2 +1,3 @@
set(PICO_PLATFORM rp2350-arm-s)
set(PICO_BOARD pico2)
+#set(OPENOCD_SERIAL E6614103E77C5A24)
diff --git a/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.h b/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.h
new file mode 100644
index 000000000..b5ce8b7e1
--- /dev/null
+++ b/hw/bsp/rp2040/boards/raspberry_pi_pico2/board.h
@@ -0,0 +1,69 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2025 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.
+ */
+
+/* metadata:
+ name: Pico2
+ url: https://www.raspberrypi.com/products/raspberry-pi-pico-2/
+*/
+
+#ifndef TUSB_BOARD_H
+#define TUSB_BOARD_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// UART and LED are already defined in pico-sdk board
+
+//--------------------------------------------------------------------+
+// PIO_USB
+//--------------------------------------------------------------------+
+// default to pico brain tester
+#define PICO_DEFAULT_PIO_USB_DP_PIN 20
+#define PICO_DEFAULT_PIO_USB_VBUSEN_PIN 22
+#define PICO_DEFAULT_PIO_USB_VBUSEN_STATE 1
+
+//--------------------------------------------------------------------
+// USB Host MAX3421E
+//--------------------------------------------------------------------
+
+#ifdef PICO_DEFAULT_SPI
+#define MAX3421_SPI PICO_DEFAULT_SPI // sdk v2
+#else
+#define MAX3421_SPI PICO_DEFAULT_SPI_INSTANCE // sdk v1
+#endif
+
+#define MAX3421_SCK_PIN PICO_DEFAULT_SPI_SCK_PIN
+#define MAX3421_MOSI_PIN PICO_DEFAULT_SPI_TX_PIN
+#define MAX3421_MISO_PIN PICO_DEFAULT_SPI_RX_PIN
+#define MAX3421_CS_PIN 10
+#define MAX3421_INTR_PIN 9
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/hw/bsp/rp2040/family.c b/hw/bsp/rp2040/family.c
index 24aa0b616..8c85c5cc8 100644
--- a/hw/bsp/rp2040/family.c
+++ b/hw/bsp/rp2040/family.c
@@ -42,10 +42,6 @@
#include "bsp/board_api.h"
#include "board.h"
-#ifdef UART_DEV
-static uart_inst_t *uart_inst;
-#endif
-
#if (CFG_TUH_ENABLED && CFG_TUH_RPI_PIO_USB) || (CFG_TUD_ENABLED && CFG_TUD_RPI_PIO_USB)
#include "pio_usb.h"
#endif
@@ -55,6 +51,36 @@ static uart_inst_t *uart_inst;
static void max3421_init(void);
#endif
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
+// LED
+#if !defined(LED_PIN) && defined(PICO_DEFAULT_LED_PIN)
+#define LED_PIN PICO_DEFAULT_LED_PIN
+#define LED_STATE_ON (!(PICO_DEFAULT_LED_PIN_INVERTED))
+#endif
+
+// Button, if not defined use BOOTSEL button
+#ifndef BUTTON_PIN
+#define BUTTON_BOOTSEL
+#define BUTTON_STATE_ACTIVE 0
+#endif
+
+// UART
+#if !defined(UART_DEV) && defined(PICO_DEFAULT_UART) && defined(LIB_PICO_STDIO_UART) && \
+ defined(PICO_DEFAULT_UART_TX_PIN) && defined(PICO_DEFAULT_UART_RX_PIN)
+#define UART_DEV PICO_DEFAULT_UART
+#define UART_TX_PIN PICO_DEFAULT_UART_TX_PIN
+#define UART_RX_PIN PICO_DEFAULT_UART_RX_PIN
+#endif
+
+#ifdef UART_DEV
+static uart_inst_t *uart_inst;
+#endif
+
+//--------------------------------------------------------------------+
+//
+//--------------------------------------------------------------------+
#ifdef BUTTON_BOOTSEL
// This example blinks the Picoboard LED when the BOOTSEL button is pressed.
//
@@ -79,7 +105,7 @@ bool __no_inline_not_in_flash_func(get_bootsel_button)(void) {
IO_QSPI_GPIO_QSPI_SS_CTRL_OEOVER_BITS);
// Note we can't call into any sleep functions in flash right now
- for (volatile int i = 0; i < 1000; ++i);
+ for (volatile int i = 0; i < 1000; ++i) {}
// The HI GPIO registers in SIO can observe and control the 6 QSPI pins.
// Note the button pulls the pin *low* when pressed.
@@ -133,12 +159,15 @@ void stdio_rtt_init(void) {
//--------------------------------------------------------------------+
//
//--------------------------------------------------------------------+
-
void board_init(void)
{
#if (CFG_TUH_ENABLED && CFG_TUH_RPI_PIO_USB) || (CFG_TUD_ENABLED && CFG_TUD_RPI_PIO_USB)
- // Set the system clock to a multiple of 120mhz for bitbanging USB with pico-usb
+ // Set the system clock to a multiple of 12mhz for bit-banging USB with pico-usb
set_sys_clock_khz(120000, true);
+ // set_sys_clock_khz(180000, true);
+ // set_sys_clock_khz(192000, true);
+ // set_sys_clock_khz(240000, true);
+ // set_sys_clock_khz(264000, true);
#ifdef PICO_DEFAULT_PIO_USB_VBUSEN_PIN
gpio_init(PICO_DEFAULT_PIO_USB_VBUSEN_PIN);
@@ -193,7 +222,6 @@ void board_init(void)
//--------------------------------------------------------------------+
// Board porting API
//--------------------------------------------------------------------+
-
void board_led_write(bool state) {
(void) state;
@@ -266,7 +294,9 @@ int board_getchar(void) {
#if CFG_TUH_ENABLED && defined(CFG_TUH_MAX3421) && CFG_TUH_MAX3421
void max3421_int_handler(uint gpio, uint32_t event_mask) {
- if (!(gpio == MAX3421_INTR_PIN && event_mask & GPIO_IRQ_EDGE_FALL)) return;
+ if (!(gpio == MAX3421_INTR_PIN && event_mask & GPIO_IRQ_EDGE_FALL)) {
+ return;
+ }
tuh_int_handler(BOARD_TUH_RHPORT, true);
}
diff --git a/hw/bsp/rp2040/family.cmake b/hw/bsp/rp2040/family.cmake
index b2b01b1cf..2182e9ad1 100644
--- a/hw/bsp/rp2040/family.cmake
+++ b/hw/bsp/rp2040/family.cmake
@@ -31,7 +31,9 @@ elseif (PICO_PLATFORM STREQUAL "rp2350-riscv")
set(OPENOCD_TARGET rp2350-riscv)
endif()
-set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -f target/${OPENOCD_TARGET}.cfg -c \"adapter speed 5000\"")
+if (NOT OPENOCD_OPTION)
+ set(OPENOCD_OPTION "-f interface/cmsis-dap.cfg -f target/${OPENOCD_TARGET}.cfg -c \"adapter speed 5000\"")
+endif()
if (NOT PICO_TINYUSB_PATH)
set(PICO_TINYUSB_PATH ${TOP})
@@ -111,6 +113,7 @@ target_sources(tinyusb_host_base INTERFACE
${TOP}/src/host/hub.c
${TOP}/src/class/cdc/cdc_host.c
${TOP}/src/class/hid/hid_host.c
+ ${TOP}/src/class/midi/midi_host.c
${TOP}/src/class/msc/msc_host.c
${TOP}/src/class/vendor/vendor_host.c
)
@@ -143,6 +146,7 @@ target_sources(tinyusb_bsp INTERFACE
)
target_include_directories(tinyusb_bsp INTERFACE
${TOP}/hw
+ ${CMAKE_CURRENT_LIST_DIR}/boards/${BOARD}
)
target_link_libraries(tinyusb_bsp INTERFACE
pico_unique_id
diff --git a/hw/bsp/rp2040/rp2350-openocd.cfg b/hw/bsp/rp2040/rp2350-openocd.cfg
new file mode 100644
index 000000000..52c71cd99
--- /dev/null
+++ b/hw/bsp/rp2040/rp2350-openocd.cfg
@@ -0,0 +1,3 @@
+source [find interface/cmsis-dap.cfg]
+adapter speed 5000
+source [find target/rp2350.cfg]
diff --git a/hw/bsp/same70_xplained/board.mk b/hw/bsp/same70_xplained/board.mk
index 3edc128a5..60702f14a 100644
--- a/hw/bsp/same70_xplained/board.mk
+++ b/hw/bsp/same70_xplained/board.mk
@@ -14,6 +14,14 @@ CFLAGS += \
# suppress following warnings from mcu driver
CFLAGS += -Wno-error=unused-parameter -Wno-error=cast-align -Wno-error=redundant-decls
+SPEED ?= high
+
+ifeq ($(SPEED), high)
+ CFLAGS += -DBOARD_TUD_MAX_SPEED=OPT_MODE_HIGH_SPEED
+else
+ CFLAGS += -DBOARD_TUD_MAX_SPEED=OPT_MODE_FULL_SPEED
+endif
+
# SAM driver is flooded with -Wcast-qual which slow down complication significantly
CFLAGS_SKIP += -Wcast-qual
diff --git a/hw/bsp/stm32f4/boards/stm32f407blackvet/board.mk b/hw/bsp/stm32f4/boards/stm32f407blackvet/board.mk
index 2593978ec..c46a78f81 100644
--- a/hw/bsp/stm32f4/boards/stm32f407blackvet/board.mk
+++ b/hw/bsp/stm32f4/boards/stm32f407blackvet/board.mk
@@ -1,12 +1,12 @@
CFLAGS += -DSTM32F407xx
# GCC
-GCC_SRC_S += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f407xx.s
-GCC_LD_FILE = $(BOARD_PATH)/STM32F407VETX_FLASH.ld
+SRC_S_GCC += $(ST_CMSIS)/Source/Templates/gcc/startup_stm32f407xx.s
+LD_FILE_GCC = $(BOARD_PATH)/STM32F407VETx_FLASH.ld
# IAR
-IAR_SRC_S += $(ST_CMSIS)/Source/Templates/iar/startup_stm32f407xx.s
-IAR_LD_FILE = $(ST_CMSIS)/Source/Templates/iar/linker/stm32f407xx_flash.icf
+SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_stm32f407xx.s
+LD_FILE_IAR = $(ST_CMSIS)/Source/Templates/iar/linker/stm32f407xx_flash.icf
# For flash-jlink target
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 7b3ab4d42..55c52033c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -29,6 +29,7 @@ function(tinyusb_target_add TARGET)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/host/hub.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/cdc/cdc_host.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/hid/hid_host.c
+ ${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/midi/midi_host.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/msc/msc_host.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/class/vendor/vendor_host.c
# typec
diff --git a/src/class/audio/audio.h b/src/class/audio/audio.h
index 2f97c0f23..0d1acadcc 100644
--- a/src/class/audio/audio.h
+++ b/src/class/audio/audio.h
@@ -661,6 +661,7 @@ typedef struct TU_ATTR_PACKED
uint16_t wTotalLength ; ///< Total number of bytes returned for the class-specific AudioControl interface descriptor. Includes the combined length of this descriptor header and all Clock Source, Unit and Terminal descriptors.
uint8_t bmControls ; ///< See: audio_cs_ac_interface_control_pos_t.
} audio_desc_cs_ac_interface_t;
+TU_VERIFY_STATIC(sizeof(audio_desc_cs_ac_interface_t) == 9, "size is not correct");
/// AUDIO Clock Source Descriptor (4.7.2.1)
typedef struct TU_ATTR_PACKED
diff --git a/src/class/audio/audio_device.c b/src/class/audio/audio_device.c
index 8a130b7e2..7a6fd453f 100644
--- a/src/class/audio/audio_device.c
+++ b/src/class/audio/audio_device.c
@@ -208,15 +208,15 @@ tu_static CFG_TUD_MEM_SECTION struct {
#endif// CFG_TUD_AUDIO_ENABLE_EP_OUT && (USE_LINEAR_BUFFER || CFG_TUD_AUDIO_ENABLE_DECODING)
// Control buffers
-tu_static uint8_t ctrl_buf_1[CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ];
-
-#if CFG_TUD_AUDIO > 1
-tu_static uint8_t ctrl_buf_2[CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ];
-#endif
-
-#if CFG_TUD_AUDIO > 2
-tu_static uint8_t ctrl_buf_3[CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ];
-#endif
+tu_static CFG_TUD_MEM_SECTION struct {
+ TUD_EPBUF_DEF(buf1, CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ);
+ #if CFG_TUD_AUDIO > 1
+ TUD_EPBUF_DEF(buf2, CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ);
+ #endif
+ #if CFG_TUD_AUDIO > 2
+ TUD_EPBUF_DEF(buf3, CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ);
+ #endif
+} ctrl_buf;
// Active alternate setting of interfaces
tu_static uint8_t alt_setting_1[CFG_TUD_AUDIO_FUNC_1_N_AS_INT];
@@ -628,10 +628,6 @@ static uint8_t audiod_get_audio_fct_idx(audiod_function_t *audio);
#if (CFG_TUD_AUDIO_ENABLE_EP_IN && (CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL || CFG_TUD_AUDIO_ENABLE_ENCODING)) || (CFG_TUD_AUDIO_ENABLE_EP_OUT && CFG_TUD_AUDIO_ENABLE_DECODING)
static void audiod_parse_for_AS_params(audiod_function_t *audio, uint8_t const *p_desc, uint8_t const *p_desc_end, uint8_t const as_itf);
-
-static inline uint8_t tu_desc_subtype(void const *desc) {
- return ((uint8_t const *) desc)[2];
-}
#endif
#if CFG_TUD_AUDIO_ENABLE_EP_IN && CFG_TUD_AUDIO_EP_IN_FLOW_CONTROL
@@ -1227,18 +1223,18 @@ void audiod_init(void) {
// Initialize control buffers
switch (i) {
case 0:
- audio->ctrl_buf = ctrl_buf_1;
+ audio->ctrl_buf = ctrl_buf.buf1;
audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_1_CTRL_BUF_SZ;
break;
#if CFG_TUD_AUDIO > 1 && CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ > 0
case 1:
- audio->ctrl_buf = ctrl_buf_2;
+ audio->ctrl_buf = ctrl_buf.buf2;
audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_2_CTRL_BUF_SZ;
break;
#endif
#if CFG_TUD_AUDIO > 2 && CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ > 0
case 2:
- audio->ctrl_buf = ctrl_buf_3;
+ audio->ctrl_buf = ctrl_buf.buf3;
audio->ctrl_buf_sz = CFG_TUD_AUDIO_FUNC_3_CTRL_BUF_SZ;
break;
#endif
diff --git a/src/class/cdc/cdc_device.c b/src/class/cdc/cdc_device.c
index efb672201..4d19adeb4 100644
--- a/src/class/cdc/cdc_device.c
+++ b/src/class/cdc/cdc_device.c
@@ -82,7 +82,7 @@ typedef struct {
static cdcd_interface_t _cdcd_itf[CFG_TUD_CDC];
CFG_TUD_MEM_SECTION static cdcd_epbuf_t _cdcd_epbuf[CFG_TUD_CDC];
-static tud_cdc_configure_fifo_t _cdcd_fifo_cfg;
+static tud_cdc_configure_t _cdcd_cfg = TUD_CDC_CONFIGURE_DEFAULT();
static bool _prep_out_transaction(uint8_t itf) {
const uint8_t rhport = 0;
@@ -119,9 +119,9 @@ static bool _prep_out_transaction(uint8_t itf) {
// APPLICATION API
//--------------------------------------------------------------------+
-bool tud_cdc_configure_fifo(const tud_cdc_configure_fifo_t* cfg) {
- TU_VERIFY(cfg);
- _cdcd_fifo_cfg = (*cfg);
+bool tud_cdc_configure(const tud_cdc_configure_t* driver_cfg) {
+ TU_VERIFY(driver_cfg);
+ _cdcd_cfg = *driver_cfg;
return true;
}
@@ -175,7 +175,7 @@ void tud_cdc_n_read_flush(uint8_t itf) {
//--------------------------------------------------------------------+
uint32_t tud_cdc_n_write(uint8_t itf, const void* buffer, uint32_t bufsize) {
cdcd_interface_t* p_cdc = &_cdcd_itf[itf];
- uint16_t ret = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX));
+ uint16_t wr_count = tu_fifo_write_n(&p_cdc->tx_ff, buffer, (uint16_t) TU_MIN(bufsize, UINT16_MAX));
// flush if queue more than packet size
if (tu_fifo_count(&p_cdc->tx_ff) >= BULK_PACKET_SIZE
@@ -186,7 +186,7 @@ uint32_t tud_cdc_n_write(uint8_t itf, const void* buffer, uint32_t bufsize) {
tud_cdc_n_write_flush(itf);
}
- return ret;
+ return wr_count;
}
uint32_t tud_cdc_n_write_flush(uint8_t itf) {
@@ -233,8 +233,6 @@ bool tud_cdc_n_write_clear(uint8_t itf) {
//--------------------------------------------------------------------+
void cdcd_init(void) {
tu_memclr(_cdcd_itf, sizeof(_cdcd_itf));
- tu_memclr(&_cdcd_fifo_cfg, sizeof(_cdcd_fifo_cfg));
-
for (uint8_t i = 0; i < CFG_TUD_CDC; i++) {
cdcd_interface_t* p_cdc = &_cdcd_itf[i];
@@ -249,10 +247,10 @@ void cdcd_init(void) {
// Config RX fifo
tu_fifo_config(&p_cdc->rx_ff, p_cdc->rx_ff_buf, TU_ARRAY_SIZE(p_cdc->rx_ff_buf), 1, false);
- // Config TX fifo as overwritable at initialization and will be changed to non-overwritable
- // if terminal supports DTR bit. Without DTR we do not know if data is actually polled by terminal.
- // In this way, the most current data is prioritized.
- tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, true);
+ // TX fifo can be configured to change to overwritable if not connected (DTR bit not set). Without DTR we do not
+ // know if data is actually polled by terminal. This way the most current data is prioritized.
+ // Default: is overwritable
+ tu_fifo_config(&p_cdc->tx_ff, p_cdc->tx_ff_buf, TU_ARRAY_SIZE(p_cdc->tx_ff_buf), 1, _cdcd_cfg.tx_overwritabe_if_not_connected);
#if OSAL_MUTEX_REQUIRED
osal_mutex_t mutex_rd = osal_mutex_create(&p_cdc->rx_ff_mutex);
@@ -294,13 +292,13 @@ void cdcd_reset(uint8_t rhport) {
cdcd_interface_t* p_cdc = &_cdcd_itf[i];
tu_memclr(p_cdc, ITF_MEM_RESET_SIZE);
- if (!_cdcd_fifo_cfg.rx_persistent) {
+ if (!_cdcd_cfg.rx_persistent) {
tu_fifo_clear(&p_cdc->rx_ff);
}
- if (!_cdcd_fifo_cfg.tx_persistent) {
+ if (!_cdcd_cfg.tx_persistent) {
tu_fifo_clear(&p_cdc->tx_ff);
}
- tu_fifo_set_overwritable(&p_cdc->tx_ff, true);
+ tu_fifo_set_overwritable(&p_cdc->tx_ff, _cdcd_cfg.tx_overwritabe_if_not_connected);
}
}
@@ -414,8 +412,12 @@ bool cdcd_control_xfer_cb(uint8_t rhport, uint8_t stage, const tusb_control_requ
p_cdc->line_state = (uint8_t) request->wValue;
- // Disable fifo overwriting if DTR bit is set
- tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr);
+ // If enabled: fifo overwriting is disabled if DTR bit is set and vice versa
+ if (_cdcd_cfg.tx_overwritabe_if_not_connected) {
+ tu_fifo_set_overwritable(&p_cdc->tx_ff, !dtr);
+ } else {
+ tu_fifo_set_overwritable(&p_cdc->tx_ff, false);
+ }
TU_LOG_DRV(" Set Control Line State: DTR = %d, RTS = %d\r\n", dtr, rts);
@@ -496,7 +498,7 @@ bool cdcd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_
// xferred_bytes is multiple of EP Packet size and not zero
if (!tu_fifo_count(&p_cdc->tx_ff) && xferred_bytes && (0 == (xferred_bytes & (BULK_PACKET_SIZE - 1)))) {
if (usbd_edpt_claim(rhport, p_cdc->ep_in)) {
- usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0);
+ TU_ASSERT(usbd_edpt_xfer(rhport, p_cdc->ep_in, NULL, 0));
}
}
}
diff --git a/src/class/cdc/cdc_device.h b/src/class/cdc/cdc_device.h
index 2d5ba2575..b653ebd74 100644
--- a/src/class/cdc/cdc_device.h
+++ b/src/class/cdc/cdc_device.h
@@ -48,14 +48,24 @@
//--------------------------------------------------------------------+
// Driver Configuration
//--------------------------------------------------------------------+
-
typedef struct TU_ATTR_PACKED {
- uint8_t rx_persistent : 1; // keep rx fifo on bus reset or disconnect
- uint8_t tx_persistent : 1; // keep tx fifo on bus reset or disconnect
-} tud_cdc_configure_fifo_t;
+ uint8_t rx_persistent : 1; // keep rx fifo data even with bus reset or disconnect
+ uint8_t tx_persistent : 1; // keep tx fifo data even with reset or disconnect
+ uint8_t tx_overwritabe_if_not_connected : 1; // if not connected, tx fifo can be overwritten
+} tud_cdc_configure_t;
-// Configure CDC FIFOs behavior
-bool tud_cdc_configure_fifo(tud_cdc_configure_fifo_t const* cfg);
+#define TUD_CDC_CONFIGURE_DEFAULT() { \
+ .rx_persistent = 0, \
+ .tx_persistent = 0, \
+ .tx_overwritabe_if_not_connected = 1, \
+}
+
+// Configure CDC driver behavior
+bool tud_cdc_configure(const tud_cdc_configure_t* driver_cfg);
+
+// Backward compatible
+#define tud_cdc_configure_fifo_t tud_cdc_configure_t
+#define tud_cdc_configure_fifo tud_cdc_configure
//--------------------------------------------------------------------+
// Application API (Multiple Ports) i.e. CFG_TUD_CDC > 1
diff --git a/src/class/cdc/cdc_host.c b/src/class/cdc/cdc_host.c
index e817ebc7e..4058857c5 100644
--- a/src/class/cdc/cdc_host.c
+++ b/src/class/cdc/cdc_host.c
@@ -691,10 +691,10 @@ bool cdch_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t
}
} else if ( ep_addr == p_cdc->stream.rx.ep_addr ) {
#if CFG_TUH_CDC_FTDI
- if (p_cdc->serial_drid == SERIAL_DRIVER_FTDI) {
+ if (p_cdc->serial_drid == SERIAL_DRIVER_FTDI && xferred_bytes > 2) {
// FTDI reserve 2 bytes for status
// uint8_t status[2] = {p_cdc->stream.rx.ep_buf[0], p_cdc->stream.rx.ep_buf[1]};
- tu_edpt_stream_read_xfer_complete_offset(&p_cdc->stream.rx, xferred_bytes, 2);
+ tu_edpt_stream_read_xfer_complete_with_buf(&p_cdc->stream.rx, p_cdc->stream.rx.ep_buf+2, xferred_bytes-2);
}else
#endif
{
diff --git a/src/class/cdc/cdc_host.h b/src/class/cdc/cdc_host.h
index df975b2f0..8c5399534 100644
--- a/src/class/cdc/cdc_host.h
+++ b/src/class/cdc/cdc_host.h
@@ -49,22 +49,22 @@
// RX FIFO size
#ifndef CFG_TUH_CDC_RX_BUFSIZE
-#define CFG_TUH_CDC_RX_BUFSIZE USBH_EPSIZE_BULK_MAX
+#define CFG_TUH_CDC_RX_BUFSIZE TUH_EPSIZE_BULK_MPS
#endif
// RX Endpoint size
#ifndef CFG_TUH_CDC_RX_EPSIZE
-#define CFG_TUH_CDC_RX_EPSIZE USBH_EPSIZE_BULK_MAX
+#define CFG_TUH_CDC_RX_EPSIZE TUH_EPSIZE_BULK_MPS
#endif
// TX FIFO size
#ifndef CFG_TUH_CDC_TX_BUFSIZE
-#define CFG_TUH_CDC_TX_BUFSIZE USBH_EPSIZE_BULK_MAX
+#define CFG_TUH_CDC_TX_BUFSIZE TUH_EPSIZE_BULK_MPS
#endif
// TX Endpoint size
#ifndef CFG_TUH_CDC_TX_EPSIZE
-#define CFG_TUH_CDC_TX_EPSIZE USBH_EPSIZE_BULK_MAX
+#define CFG_TUH_CDC_TX_EPSIZE TUH_EPSIZE_BULK_MPS
#endif
//--------------------------------------------------------------------+
diff --git a/src/class/hid/hid.h b/src/class/hid/hid.h
index db9a500ee..c2434c20d 100644
--- a/src/class/hid/hid.h
+++ b/src/class/hid/hid.h
@@ -325,6 +325,29 @@ typedef enum
/// @}
+//--------------------------------------------------------------------+
+// Digitizer Stylus Pen
+//--------------------------------------------------------------------+
+/** \addtogroup ClassDriver_HID_Stylus Stylus
+ * @{ */
+
+// Standard Stylus Pen Report.
+typedef struct TU_ATTR_PACKED
+{
+ uint8_t attr; /**< Attribute mask for describing current status of the stylus pen. */
+ uint16_t x; /**< Current x position of the mouse. */
+ uint16_t y; /**< Current y position of the mouse. */
+} hid_stylus_report_t;
+
+// Standard Stylus Pen Attributes Bitmap.
+typedef enum
+{
+ STYLUS_ATTR_TIP_SWITCH = TU_BIT(0), ///< Tip switch
+ STYLUS_ATTR_IN_RANGE = TU_BIT(1), ///< In-range bit.
+} hid_stylus_attr_bm_t;
+
+/// @}
+
//--------------------------------------------------------------------+
// Keyboard
//--------------------------------------------------------------------+
@@ -740,6 +763,21 @@ enum {
//--------------------------------------------------------------------+
// Usage Table
+/* Usage Types Data
+ Sel Selector Array
+ SV Static Value Constant, Variable, Absolute
+ SF Static Flag Constant, Variable, Absolute
+ DV Dynamic Value Constant, Variable, Absolute
+ DF Dynamic Flag Constant, Variable, Absolute
+*/
+/* Usage Types Collection
+ NAry Named Array Logical
+ CA Collection Application Application
+ CL Collection Logical Logical
+ CP Collection Physical Physical
+ US Usage Switch Logical
+ UM Usage Modifier Logical
+*/
//--------------------------------------------------------------------+
/// HID Usage Table - Table 1: Usage Page Summary
@@ -759,8 +797,14 @@ enum {
HID_USAGE_PAGE_DIGITIZER = 0x0d,
HID_USAGE_PAGE_PID = 0x0f,
HID_USAGE_PAGE_UNICODE = 0x10,
- HID_USAGE_PAGE_ALPHA_DISPLAY = 0x14,
- HID_USAGE_PAGE_MEDICAL = 0x40,
+ HID_USAGE_PAGE_SOC = 0x11,
+ HID_USAGE_PAGE_EYE_AND_HEAD_TRACKERS = 0x12,
+ // 0x13 is reserved
+ HID_USAGE_PAGE_AUXILIARY_DISPLAY = 0x14,
+ // 0x15 - 0x1f is reserved
+ HID_USAGE_PAGE_SENSORS = 0x20,
+ // 0x21 - 0x3f is reserved
+ HID_USAGE_PAGE_MEDICAL_INSTRUMENT = 0x40,
HID_USAGE_PAGE_LIGHTING_AND_ILLUMINATION = 0x59,
HID_USAGE_PAGE_MONITOR = 0x80, // 0x80 - 0x83
HID_USAGE_PAGE_POWER = 0x84, // 0x084 - 0x87
@@ -846,7 +890,6 @@ enum {
HID_USAGE_DESKTOP_SYSTEM_DISPLAY_LCD_AUTOSCALE = 0xB7
};
-
/// HID Usage Table: Consumer Page (0x0C)
/// Only contains controls that supported by Windows (whole list is too long)
enum {
@@ -905,48 +948,125 @@ enum {
HID_USAGE_CONSUMER_AC_PAN = 0x0238,
};
-/// HID Usage Table - Lighting And Illumination Page (0x59)
+/// HID Usage Table: Digitizer Page (0x0D)
enum {
- HID_USAGE_LIGHTING_LAMP_ARRAY = 0x01,
- HID_USAGE_LIGHTING_LAMP_ARRAY_ATTRIBUTES_REPORT = 0x02,
- HID_USAGE_LIGHTING_LAMP_COUNT = 0x03,
- HID_USAGE_LIGHTING_BOUNDING_BOX_WIDTH_IN_MICROMETERS = 0x04,
- HID_USAGE_LIGHTING_BOUNDING_BOX_HEIGHT_IN_MICROMETERS = 0x05,
- HID_USAGE_LIGHTING_BOUNDING_BOX_DEPTH_IN_MICROMETERS = 0x06,
- HID_USAGE_LIGHTING_LAMP_ARRAY_KIND = 0x07,
- HID_USAGE_LIGHTING_MIN_UPDATE_INTERVAL_IN_MICROSECONDS = 0x08,
- HID_USAGE_LIGHTING_LAMP_ATTRIBUTES_REQUEST_REPORT = 0x20,
- HID_USAGE_LIGHTING_LAMP_ID = 0x21,
- HID_USAGE_LIGHTING_LAMP_ATTRIBUTES_RESPONSE_REPORT = 0x22,
- HID_USAGE_LIGHTING_POSITION_X_IN_MICROMETERS = 0x23,
- HID_USAGE_LIGHTING_POSITION_Y_IN_MICROMETERS = 0x24,
- HID_USAGE_LIGHTING_POSITION_Z_IN_MICROMETERS = 0x25,
- HID_USAGE_LIGHTING_LAMP_PURPOSES = 0x26,
- HID_USAGE_LIGHTING_UPDATE_LATENCY_IN_MICROSECONDS = 0x27,
- HID_USAGE_LIGHTING_RED_LEVEL_COUNT = 0x28,
- HID_USAGE_LIGHTING_GREEN_LEVEL_COUNT = 0x29,
- HID_USAGE_LIGHTING_BLUE_LEVEL_COUNT = 0x2A,
- HID_USAGE_LIGHTING_INTENSITY_LEVEL_COUNT = 0x2B,
- HID_USAGE_LIGHTING_IS_PROGRAMMABLE = 0x2C,
- HID_USAGE_LIGHTING_INPUT_BINDING = 0x2D,
- HID_USAGE_LIGHTING_LAMP_MULTI_UPDATE_REPORT = 0x50,
- HID_USAGE_LIGHTING_RED_UPDATE_CHANNEL = 0x51,
- HID_USAGE_LIGHTING_GREEN_UPDATE_CHANNEL = 0x52,
- HID_USAGE_LIGHTING_BLUE_UPDATE_CHANNEL = 0x53,
- HID_USAGE_LIGHTING_INTENSITY_UPDATE_CHANNEL = 0x54,
- HID_USAGE_LIGHTING_LAMP_UPDATE_FLAGS = 0x55,
- HID_USAGE_LIGHTING_LAMP_RANGE_UPDATE_REPORT = 0x60,
- HID_USAGE_LIGHTING_LAMP_ID_START = 0x61,
- HID_USAGE_LIGHTING_LAMP_ID_END = 0x62,
- HID_USAGE_LIGHTING_LAMP_ARRAY_CONTROL_REPORT = 0x70,
- HID_USAGE_LIGHTING_AUTONOMOUS_MODE = 0x71,
-};
+ HID_USAGE_DIGITIZER_UNDEFINED = 0x00,
+ HID_USAGE_DIGITIZER_DIGITIZER = 0x01, // CA
+ HID_USAGE_DIGITIZER_PEN = 0x02, // CA
+ HID_USAGE_DIGITIZER_LIGHT_PEN = 0x03, // CA
+ HID_USAGE_DIGITIZER_TOUCH_SCREEN = 0x04, // CA
+ HID_USAGE_DIGITIZER_TOUCH_PAD = 0x05, // CA
+ HID_USAGE_DIGITIZER_WHITEBOARD = 0x06, // CA
+ HID_USAGE_DIGITIZER_COORDINATE_MEASURING_MACHINE = 0x07, // CA
+ HID_USAGE_DIGITIZER_3D_DIGITIZER = 0x08, // CA
+ HID_USAGE_DIGITIZER_STEREO_PLOTTER = 0x09, // CA
+ HID_USAGE_DIGITIZER_ARTICULATED_ARM = 0x0A, // CA
+ HID_USAGE_DIGITIZER_ARMATURE = 0x0B, // CA
+ HID_USAGE_DIGITIZER_MULTIPLE_POINT_DIGITIZER = 0x0C, // CA
+ HID_USAGE_DIGITIZER_FREE_SPACE_WAND = 0x0D, // CA
+ HID_USAGE_DIGITIZER_DEVICE_CONFIGURATION = 0x0E, // CA
+ HID_USAGE_DIGITIZER_CAPACITIVE_HEAT_MAP_DIGITIZER = 0x0F, // CA
+ // Reserved (0x10 - 0x1F)
+ HID_USAGE_DIGITIZER_STYLUS = 0x20, // CA/CL
+ HID_USAGE_DIGITIZER_PUCK = 0x21, // CL
+ HID_USAGE_DIGITIZER_FINGER = 0x22, // CL
+ HID_USAGE_DIGITIZER_DEVICE_SETTINGS = 0x23, // CL
+ HID_USAGE_DIGITIZER_CHARACTER_GESTURE = 0x24, // CL
+ // Reserved (0x25 - 0x2F)
+ HID_USAGE_DIGITIZER_TIP_PRESSURE = 0x30, // DV
+ HID_USAGE_DIGITIZER_BARREL_PRESSURE = 0x31, // DV
+ HID_USAGE_DIGITIZER_IN_RANGE = 0x32, // MC
+ HID_USAGE_DIGITIZER_TOUCH = 0x33, // MC
+ HID_USAGE_DIGITIZER_UNTOUCH = 0x34, // OSC
+ HID_USAGE_DIGITIZER_TAP = 0x35, // OSC
+ HID_USAGE_DIGITIZER_QUALITY = 0x36, // DV
+ HID_USAGE_DIGITIZER_DATA_VALID = 0x37, // MC
+ HID_USAGE_DIGITIZER_TRANSDUCER_INDEX = 0x38, // DV
+ HID_USAGE_DIGITIZER_TABLET_FUNCTION_KEYS = 0x39, // CL
+ HID_USAGE_DIGITIZER_PROGRAM_CHANGE_KEYS = 0x3A, // CL
+ HID_USAGE_DIGITIZER_BATTERY_STRENGTH = 0x3B, // DV
+ HID_USAGE_DIGITIZER_INVERT = 0x3C, // MC
+ HID_USAGE_DIGITIZER_X_TILT = 0x3D, // DV
+ HID_USAGE_DIGITIZER_Y_TILT = 0x3E, // DV
+ HID_USAGE_DIGITIZER_AZIMUTH = 0x3F, // DV
+ HID_USAGE_DIGITIZER_ALTITUDE = 0x40, // DV
+ HID_USAGE_DIGITIZER_TWIST = 0x41, // DV
+ HID_USAGE_DIGITIZER_TIP_SWITCH = 0x42, // MC
+ HID_USAGE_DIGITIZER_SECONDARY_TIP_SWITCH = 0x43, // MC
+ HID_USAGE_DIGITIZER_BARREL_SWITCH = 0x44, // MC
+ HID_USAGE_DIGITIZER_ERASER = 0x45, // MC
+ HID_USAGE_DIGITIZER_TABLET_PICK = 0x46, // MC
+ HID_USAGE_DIGITIZER_TOUCH_VALID = 0x47, // MC
+ HID_USAGE_DIGITIZER_WIDTH = 0x48, // DV
+ HID_USAGE_DIGITIZER_HEIGHT = 0x49, // DV
+ // Reserved (0x4A - 0x50)
+ HID_USAGE_DIGITIZER_CONTACT_IDENTIFIER = 0x51, // DV
+ HID_USAGE_DIGITIZER_DEVICE_MODE = 0x52, // DV
+ HID_USAGE_DIGITIZER_DEVICE_IDENTIFIER = 0x53, // DV/SV
+ HID_USAGE_DIGITIZER_CONTACT_COUNT = 0x54, // DV
+ HID_USAGE_DIGITIZER_CONTACT_COUNT_MAXIMUM = 0x55, // SV
+ HID_USAGE_DIGITIZER_SCAN_TIME = 0x56, // DV
+ HID_USAGE_DIGITIZER_SURFACE_SWITCH = 0x57, // DF
+ HID_USAGE_DIGITIZER_BUTTON_SWITCH = 0x58, // DF
+ HID_USAGE_DIGITIZER_PAD_TYPE = 0x59, // SF
+ HID_USAGE_DIGITIZER_TRANSDUCER_SERIAL_NUMBER = 0x5B, // SV
+ HID_USAGE_DIGITIZER_PREFERRED_COLOR = 0x5C, // DV
+ HID_USAGE_DIGITIZER_PREFERRED_COLOR_LOCKED = 0x5D, // MC
+ HID_USAGE_DIGITIZER_PREFERRED_LINE_WIDTH = 0x5E, // DV
+ HID_USAGE_DIGITIZER_PREFERRED_LINE_WIDTH_LOCKED = 0x5F, // MC
+ HID_USAGE_DIGITIZER_LATENCY_MODE = 0x60, // DF
+ HID_USAGE_DIGITIZER_GESTURE_CHARACTER_QUALITY = 0x61, // DV
+ HID_USAGE_DIGITIZER_CHARACTER_GESTURE_DATA_LENGTH = 0x62, // DV
+ HID_USAGE_DIGITIZER_CHARACTER_GESTURE_DATA = 0x63, // DV
+ HID_USAGE_DIGITIZER_GESTURE_CHARACTER_ENCODING = 0x64, // NAry
+ HID_USAGE_DIGITIZER_UTF8_CHARACTER_GESTURE_ENCODING = 0x65, // Sel
+ HID_USAGE_DIGITIZER_UTF16_LE_CHARACTER_GESTURE_ENCODING = 0x66, // Sel
+ HID_USAGE_DIGITIZER_UTF16_BE_CHARACTER_GESTURE_ENCODING = 0x67, // Sel
+ HID_USAGE_DIGITIZER_UTF32_LE_CHARACTER_GESTURE_ENCODING = 0x68, // Sel
+ HID_USAGE_DIGITIZER_UTF32_BE_CHARACTER_GESTURE_ENCODING = 0x69, // Sel
+ HID_USAGE_DIGITIZER_CAPACITIVE_HEAT_MAP_VENDOR_ID = 0x6A, // SV
+ HID_USAGE_DIGITIZER_CAPACITIVE_HEAT_MAP_VERSION = 0x6B, // SV
+ HID_USAGE_DIGITIZER_CAPACITIVE_HEAT_MAP_FRAME_DATA = 0x6C, // DV
+ HID_USAGE_DIGITIZER_GESTURE_CHARACTER_ENABLE = 0x6D, // DF
+ HID_USAGE_DIGITIZER_TRANSDUCER_SERIAL_NUMBER_PART2 = 0x6E, // SV
+ HID_USAGE_DIGITIZER_NO_PREFERRED_COLOR = 0x6F, // DF
+ HID_USAGE_DIGITIZER_PREFERRED_LINE_STYLE = 0x70, // NAry
+ HID_USAGE_DIGITIZER_PREFERRED_LINE_STYLE_LOCKED = 0x71, // MC
+ HID_USAGE_DIGITIZER_INK = 0x72, // Sel
+ HID_USAGE_DIGITIZER_PENCIL = 0x73, // Sel
+ HID_USAGE_DIGITIZER_HIGHLIGHTER = 0x74, // Sel
+ HID_USAGE_DIGITIZER_CHISEL_MARKER = 0x75, // Sel
+ HID_USAGE_DIGITIZER_BRUSH = 0x76, // Sel
+ HID_USAGE_DIGITIZER_NO_PREFERENCE = 0x77, // Sel
+ // Reserved (0x78 - 0x7F)
+ HID_USAGE_DIGITIZER_DIGITIZER_DIAGNOSTIC = 0x80, // CL
+ HID_USAGE_DIGITIZER_DIGITIZER_ERROR = 0x81, // NAry
+ HID_USAGE_DIGITIZER_ERR_NORMAL_STATUS = 0x82, // Sel
+ HID_USAGE_DIGITIZER_ERR_TRANSDUCERS_EXCEEDED = 0x83, // Sel
+ HID_USAGE_DIGITIZER_ERR_FULL_TRANS_FEATURES_UNAVAILABLE = 0x84, // Sel
+ HID_USAGE_DIGITIZER_ERR_CHARGE_LOW = 0x85, // Sel
+ // Reserved (0x86 - 0x8F)
+ HID_USAGE_DIGITIZER_TRANSDUCER_SOFTWARE_INFO = 0x90, // CL
+ HID_USAGE_DIGITIZER_TRANSDUCER_VENDOR_ID = 0x91, // SV
+ HID_USAGE_DIGITIZER_TRANSDUCER_PRODUCT_ID = 0x92, // SV
+ HID_USAGE_DIGITIZER_DEVICE_SUPPORTED_PROTOCOLS = 0x93, // NAry/CL
+ HID_USAGE_DIGITIZER_TRANSDUCER_SUPPORTED_PROTOCOLS = 0x94, // NAry/CL
+ HID_USAGE_DIGITIZER_NO_PROTOCOL = 0x95, // Sel
+ HID_USAGE_DIGITIZER_WACOM_AES_PROTOCOL = 0x96, // Sel
+ HID_USAGE_DIGITIZER_USI_PROTOCOL = 0x97, // Sel
+ HID_USAGE_DIGITIZER_MICROSOFT_PEN_PROTOCOL = 0x98, // Sel
+ // Reserved (0x99 - 0x9F)
+ HID_USAGE_DIGITIZER_SUPPORTED_REPORT_RATES = 0xA0, // SV/CL
+ HID_USAGE_DIGITIZER_REPORT_RATE = 0xA1, // DV
+ HID_USAGE_DIGITIZER_TRANSDUCER_CONNECTED = 0xA2, // SF
+ HID_USAGE_DIGITIZER_SWITCH_DISABLED = 0xA3, // Sel
+ HID_USAGE_DIGITIZER_SWITCH_UNIMPLEMENTED = 0xA4, // Sel
+ HID_USAGE_DIGITIZER_TRANSDUCER_SWITCHES = 0xA5, // CL
+ HID_USAGE_DIGITIZER_TRANSDUCER_INDEX_SELECTOR = 0xA6, // DV
+ // Reserved (0xA7 - 0xAF)
+ HID_USAGE_DIGITIZER_BUTTON_PRESS_THRESHOLD = 0xB0, // DV
-/// HID Usage Table: FIDO Alliance Page (0xF1D0)
-enum {
- HID_USAGE_FIDO_U2FHID = 0x01, // U2FHID usage for top-level collection
- HID_USAGE_FIDO_DATA_IN = 0x20, // Raw IN data report
- HID_USAGE_FIDO_DATA_OUT = 0x21 // Raw OUT data report
+ // Reserved (0xB1 - 0xFFFF)
};
/// HID Usage Table: Physical Input Device Page (0x0F)
@@ -1059,6 +1179,50 @@ enum {
HID_USAGE_PID_RAM_POOL_AVAILABLE = 0xac,
};
+/// HID Usage Table - Lighting And Illumination Page (0x59)
+enum {
+ HID_USAGE_LIGHTING_LAMP_ARRAY = 0x01,
+ HID_USAGE_LIGHTING_LAMP_ARRAY_ATTRIBUTES_REPORT = 0x02,
+ HID_USAGE_LIGHTING_LAMP_COUNT = 0x03,
+ HID_USAGE_LIGHTING_BOUNDING_BOX_WIDTH_IN_MICROMETERS = 0x04,
+ HID_USAGE_LIGHTING_BOUNDING_BOX_HEIGHT_IN_MICROMETERS = 0x05,
+ HID_USAGE_LIGHTING_BOUNDING_BOX_DEPTH_IN_MICROMETERS = 0x06,
+ HID_USAGE_LIGHTING_LAMP_ARRAY_KIND = 0x07,
+ HID_USAGE_LIGHTING_MIN_UPDATE_INTERVAL_IN_MICROSECONDS = 0x08,
+ HID_USAGE_LIGHTING_LAMP_ATTRIBUTES_REQUEST_REPORT = 0x20,
+ HID_USAGE_LIGHTING_LAMP_ID = 0x21,
+ HID_USAGE_LIGHTING_LAMP_ATTRIBUTES_RESPONSE_REPORT = 0x22,
+ HID_USAGE_LIGHTING_POSITION_X_IN_MICROMETERS = 0x23,
+ HID_USAGE_LIGHTING_POSITION_Y_IN_MICROMETERS = 0x24,
+ HID_USAGE_LIGHTING_POSITION_Z_IN_MICROMETERS = 0x25,
+ HID_USAGE_LIGHTING_LAMP_PURPOSES = 0x26,
+ HID_USAGE_LIGHTING_UPDATE_LATENCY_IN_MICROSECONDS = 0x27,
+ HID_USAGE_LIGHTING_RED_LEVEL_COUNT = 0x28,
+ HID_USAGE_LIGHTING_GREEN_LEVEL_COUNT = 0x29,
+ HID_USAGE_LIGHTING_BLUE_LEVEL_COUNT = 0x2A,
+ HID_USAGE_LIGHTING_INTENSITY_LEVEL_COUNT = 0x2B,
+ HID_USAGE_LIGHTING_IS_PROGRAMMABLE = 0x2C,
+ HID_USAGE_LIGHTING_INPUT_BINDING = 0x2D,
+ HID_USAGE_LIGHTING_LAMP_MULTI_UPDATE_REPORT = 0x50,
+ HID_USAGE_LIGHTING_RED_UPDATE_CHANNEL = 0x51,
+ HID_USAGE_LIGHTING_GREEN_UPDATE_CHANNEL = 0x52,
+ HID_USAGE_LIGHTING_BLUE_UPDATE_CHANNEL = 0x53,
+ HID_USAGE_LIGHTING_INTENSITY_UPDATE_CHANNEL = 0x54,
+ HID_USAGE_LIGHTING_LAMP_UPDATE_FLAGS = 0x55,
+ HID_USAGE_LIGHTING_LAMP_RANGE_UPDATE_REPORT = 0x60,
+ HID_USAGE_LIGHTING_LAMP_ID_START = 0x61,
+ HID_USAGE_LIGHTING_LAMP_ID_END = 0x62,
+ HID_USAGE_LIGHTING_LAMP_ARRAY_CONTROL_REPORT = 0x70,
+ HID_USAGE_LIGHTING_AUTONOMOUS_MODE = 0x71,
+};
+
+/// HID Usage Table: FIDO Alliance Page (0xF1D0)
+enum {
+ HID_USAGE_FIDO_U2FHID = 0x01, // U2FHID usage for top-level collection
+ HID_USAGE_FIDO_DATA_IN = 0x20, // Raw IN data report
+ HID_USAGE_FIDO_DATA_OUT = 0x21 // Raw OUT data report
+};
+
/*--------------------------------------------------------------------
* ASCII to KEYCODE Conversion
* Expand to array of [128][2] (shift, keycode)
diff --git a/src/class/hid/hid_device.c b/src/class/hid/hid_device.c
index eedcba984..b4f24902b 100644
--- a/src/class/hid/hid_device.c
+++ b/src/class/hid/hid_device.c
@@ -194,6 +194,16 @@ bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id,
return tud_hid_n_report(instance, report_id, &report, sizeof(report));
}
+bool tud_hid_n_stylus_report(uint8_t instance, uint8_t report_id, uint8_t attrs, uint16_t x, uint16_t y) {
+ hid_stylus_report_t report = {
+ .attr = attrs,
+ .x = x,
+ .y = y,
+ };
+
+ return tud_hid_n_report(instance, report_id, &report, sizeof(report));
+}
+
//--------------------------------------------------------------------+
// USBD-CLASS API
//--------------------------------------------------------------------+
diff --git a/src/class/hid/hid_device.h b/src/class/hid/hid_device.h
index ab2e27373..fc1dbcbd8 100644
--- a/src/class/hid/hid_device.h
+++ b/src/class/hid/hid_device.h
@@ -79,6 +79,9 @@ bool tud_hid_n_abs_mouse_report(uint8_t instance, uint8_t report_id, uint8_t but
// use template layout report TUD_HID_REPORT_DESC_GAMEPAD
bool tud_hid_n_gamepad_report(uint8_t instance, uint8_t report_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons);
+// STYLUS PEN: convenient helper to send absolute stylus pen report if application
+bool tud_hid_n_stylus_report(uint8_t instance, uint8_t report_id, uint8_t attrs, uint16_t x, uint16_t y);
+
//--------------------------------------------------------------------+
// Application API (Single Port)
//--------------------------------------------------------------------+
@@ -114,6 +117,10 @@ TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_gamepad_report(uint8_t report_i
return tud_hid_n_gamepad_report(0, report_id, x, y, z, rz, rx, ry, hat, buttons);
}
+TU_ATTR_ALWAYS_INLINE static inline bool tud_hid_stylus_report(uint8_t report_id, uint8_t attrs, uint16_t x, uint16_t y) {
+ return tud_hid_n_stylus_report(0, report_id, attrs, x, y);
+}
+
//--------------------------------------------------------------------+
// Application Callbacks
//--------------------------------------------------------------------+
@@ -257,6 +264,41 @@ void tud_hid_report_failed_cb(uint8_t instance, hid_report_type_t report_type, u
HID_COLLECTION_END , \
HID_COLLECTION_END \
+// Stylus Pen Report Descriptor Template
+#define TUD_HID_REPORT_DESC_STYLUS_PEN(...) \
+ HID_USAGE_PAGE ( HID_USAGE_PAGE_DIGITIZER ) , \
+ HID_USAGE ( HID_USAGE_DIGITIZER_TOUCH_SCREEN ) , \
+ HID_COLLECTION ( HID_COLLECTION_APPLICATION ) , \
+ /* Report ID if any */\
+ __VA_ARGS__ \
+ HID_USAGE ( HID_USAGE_DIGITIZER_STYLUS ) , \
+ HID_COLLECTION ( HID_COLLECTION_PHYSICAL ) , \
+ HID_USAGE_PAGE ( HID_USAGE_DIGITIZER_TIP_SWITCH ) , \
+ HID_USAGE_PAGE ( HID_USAGE_DIGITIZER_IN_RANGE ) , \
+ HID_LOGICAL_MIN ( 0 ), \
+ HID_LOGICAL_MAX ( 1 ), \
+ HID_REPORT_SIZE ( 1 ), \
+ HID_REPORT_COUNT( 2 ), \
+ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ), \
+ HID_REPORT_SIZE ( 1 ), \
+ HID_REPORT_COUNT( 6 ), \
+ HID_INPUT ( HID_CONSTANT | HID_ARRAY | HID_ABSOLUTE), \
+ HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ), \
+ HID_PHYSICAL_MAX_N( 0x7fff, 2 ), \
+ HID_LOGICAL_MAX_N ( 0x7fff, 2 ), \
+ HID_REPORT_SIZE ( 16 ), \
+ HID_REPORT_COUNT( 1 ), \
+ HID_UNIT_EXPONENT( 0x0f ), \
+ HID_UNIT ( HID_VARIABLE | HID_NONLINEAR ), \
+ HID_PHYSICAL_MIN( 0 ), \
+ HID_PHYSICAL_MAX( 0 ), \
+ HID_USAGE ( HID_USAGE_DESKTOP_X ), \
+ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ), \
+ HID_USAGE ( HID_USAGE_DESKTOP_Y ), \
+ HID_INPUT ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ), \
+ HID_COLLECTION_END , \
+ HID_COLLECTION_END \
+
// Absolute Mouse Report Descriptor Template
#define TUD_HID_REPORT_DESC_ABSMOUSE(...) \
HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP ) ,\
diff --git a/src/class/midi/README_midi_host.md b/src/class/midi/README_midi_host.md
new file mode 100644
index 000000000..efaf7a13d
--- /dev/null
+++ b/src/class/midi/README_midi_host.md
@@ -0,0 +1,111 @@
+# MIDI HOST DRIVER
+This README file contains the design notes and limitations of the
+MIDI host driver.
+
+# MAXIMUM NUMBER OF MIDI DEVICES ATTACHED TO HOST
+In this version of the driver, only one MIDI device is supported. This
+constraint may change in the future.
+
+# MAXIMUM NUMBER OF ENDPOINTS
+Although the USB MIDI 1.0 Class specification allows an arbitrary number
+of endpoints, this driver supports at most one USB BULK DATA IN endpoint
+and one USB BULK DATA OUT endpoint. Each endpoint can support up to 16
+virtual cables. If a device has multiple IN endpoints or multiple OUT
+endpoints, it will fail to enumerate.
+
+Most USB MIDI devices contain both an IN endpoint and an OUT endpoint,
+but not all do. For example, some USB pedals only support an OUT endpoint.
+This driver allows that.
+
+# PUBLIC API
+Applications interact with this driver via 8-bit buffers of MIDI messages
+formed using the rules for sending bytes on a 5-pin DIN cable per the
+original MIDI 1.0 specification.
+
+To send a message to a device, the Host application composes a sequence
+of status and data bytes in a byte array and calls the API function.
+The arguments of the function are a pointer to the byte array, the number
+of bytes in the array, and the target virtual cable number 0-15.
+
+When the host driver receives a message from the device, the host driver
+will call a callback function that the host application registers. This
+callback function contains a pointer to a message buffer, a message length,
+and the virtual cable number of the message buffer. One complete bulk IN
+endpoint transfer might contain multiple messages targeted to different
+virtual cables.
+
+# SUBCLASS AUDIO CONTROL
+A MIDI device does not absolutely need to have an Audio Control Interface,
+unless it adheres to the USB Audio Class 2 spec, but many devices
+have them even if the devices do not have an audio streaming interface.
+Because this driver does not support audio streaming, the descriptor parser
+will skip past any audio control interface and audio streaming interface
+and open only the MIDI interface.
+
+An audio streaming host driver can use this driver by passing a pointer
+to the MIDI interface descriptor that is found after the audio streaming
+interface to the midih_open() function. That is, an audio streaming host
+driver would parse the audio control interface descriptor and then the
+audio streaming interface and endpoint descriptors. When the next descriptor
+pointer points to a MIDI interface descriptor, call midih_open() with that
+descriptor pointer.
+
+# CLASS SPECIFIC INTERFACE AND REQUESTS
+The host driver does not make use of the information in the class specific
+interface descriptors. In the future, a public API could be created to
+retrieve the string descriptors for the names of each ELEMENT,
+IN JACK and OUT JACK, and how the device describes the connections.
+
+This driver also does not support class specific requests to control
+ELEMENT items, nor does it support non-MIDI Streaming bulk endpoints.
+
+# MIDI CLASS SPECIFIC DESCRIPTOR TOTAL LENGTH FIELD IGNORED
+I have observed at least one keyboard by a leading manufacturer that
+sets the wTotalLength field of the Class-Specific MS Interface Header
+Descriptor to include the length of the MIDIStreaming Endpoint
+Descriptors. This is wrong per my reading of the specification.
+
+# MESSAGE BUFFER DETAILS
+Messages buffers composed from USB data received on the IN endpoint will never contain
+running status because USB MIDI 1.0 class does not support that. Messages
+buffers to be sent to the device on the OUT endpoint may contain running status
+(the message might come from a UART data stream from a 5-pin DIN MIDI IN
+cable on the host, for example). The driver may in the future correctly compose
+4-byte USB MIDI Class packets using the running status if need be. However,
+it does not currently do that. Also, use of running status is not a good idea
+overall because a single byte error can really mess up the data stream with no
+way to recover until the next non-real time status byte is in the message buffer.
+
+Message buffers to be sent to the device may contain Real time messages
+such as MIDI clock. Real time messages may be inserted in the message
+byte stream between status and data bytes of another message without disrupting
+the running status. However, because MIDI 1.0 class messages are sent
+as four byte packets, a real-time message so inserted will be re-ordered
+to be sent to the device in a new 4-byte packet immediately before the
+interrupted data stream.
+
+Real time messages the device sends to the host can only appear between
+the status byte and data bytes of the message in System Exclusive messages
+that are longer than 3 bytes.
+
+# POORLY FORMED USB MIDI DATA PACKETS FROM THE DEVICE
+Some devices do not properly encode the code index number (CIN) for the
+MIDI message status byte even though the 3-byte data payload correctly encodes
+the MIDI message. This driver looks to the byte after the CIN byte to decide
+how many bytes to place in the message buffer.
+
+Some devices do not properly encode the virtual cable number. If the virtual
+cable number in the CIN data byte of the packet is not less than bNumEmbMIDIJack
+for that endpoint, then the host driver assumes virtual cable 0 and does not
+report an error.
+
+Some MIDI devices will always send back exactly wMaxPacketSize bytes on
+every endpoint even if only one 4-byte packet is required (e.g., NOTE ON).
+These devices send packets with 4 packet bytes 0. This driver ignores all
+zero packets without reporting an error.
+
+# ENUMERATION FAILURES
+The host may fail to enumerate a device if it has too many endpoints, if it has
+if it has a Standard MS Transfer Bulk Data Endpoint Descriptor (not supported),
+if it has a poorly formed descriptor, or if the descriptor is too long for
+the host to read the whole thing.
diff --git a/src/class/midi/midi.h b/src/class/midi/midi.h
index 8ddcdfda2..cd67640e4 100644
--- a/src/class/midi/midi.h
+++ b/src/class/midi/midi.h
@@ -24,13 +24,8 @@
* This file is part of the TinyUSB stack.
*/
-/** \ingroup group_class
- * \defgroup ClassDriver_CDC Communication Device Class (CDC)
- * Currently only Abstract Control Model subclass is supported
- * @{ */
-
-#ifndef _TUSB_MIDI_H__
-#define _TUSB_MIDI_H__
+#ifndef TUSB_MIDI_H_
+#define TUSB_MIDI_H_
#include "common/tusb_common.h"
@@ -39,30 +34,31 @@
#endif
//--------------------------------------------------------------------+
-// Class Specific Descriptor
+// Constants
//--------------------------------------------------------------------+
+enum {
+ MIDI_VERSION_1_0 = 0x0100,
+ MIDI_VERSION_2_0 = 0x0200,
+};
-typedef enum
-{
+typedef enum {
MIDI_CS_INTERFACE_HEADER = 0x01,
MIDI_CS_INTERFACE_IN_JACK = 0x02,
MIDI_CS_INTERFACE_OUT_JACK = 0x03,
MIDI_CS_INTERFACE_ELEMENT = 0x04,
} midi_cs_interface_subtype_t;
-typedef enum
-{
- MIDI_CS_ENDPOINT_GENERAL = 0x01
+typedef enum {
+ MIDI_CS_ENDPOINT_GENERAL = 0x01,
+ MIDI_CS_ENDPOINT_GENERAL_2_0 = 0x02,
} midi_cs_endpoint_subtype_t;
-typedef enum
-{
+typedef enum {
MIDI_JACK_EMBEDDED = 0x01,
MIDI_JACK_EXTERNAL = 0x02
} midi_jack_type_t;
-typedef enum
-{
+typedef enum {
MIDI_CIN_MISC = 0,
MIDI_CIN_CABLE_EVENT = 1,
MIDI_CIN_SYSCOM_2BYTE = 2, // 2 byte system common message e.g MTC, SongSelect
@@ -82,8 +78,7 @@ typedef enum
} midi_code_index_number_t;
// MIDI 1.0 status byte
-enum
-{
+enum {
//------------- System Exclusive -------------//
MIDI_STATUS_SYSEX_START = 0xF0,
MIDI_STATUS_SYSEX_END = 0xF7,
@@ -106,80 +101,54 @@ enum
MIDI_STATUS_SYSREAL_SYSTEM_RESET = 0xFF,
};
+enum {
+ MIDI_MAX_DATA_VAL = 0x7F,
+};
+
+//--------------------------------------------------------------------+
+// Class Specific Descriptor
+//--------------------------------------------------------------------+
+
/// MIDI Interface Header Descriptor
-typedef struct TU_ATTR_PACKED
-{
- uint8_t bLength ; ///< Size of this descriptor in bytes.
- uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
- uint8_t bDescriptorSubType ; ///< Descriptor SubType
- uint16_t bcdMSC ; ///< MidiStreaming SubClass release number in Binary-Coded Decimal
- uint16_t wTotalLength ;
+typedef struct TU_ATTR_PACKED {
+ uint8_t bLength; ///< Size of this descriptor in bytes.
+ uint8_t bDescriptorType; ///< must be TUSB_DESC_CS_INTERFACE
+ uint8_t bDescriptorSubType;///< Descriptor SubType
+ uint16_t bcdMSC; ///< MidiStreaming SubClass release number in Binary-Coded Decimal
+ uint16_t wTotalLength;
} midi_desc_header_t;
+TU_VERIFY_STATIC(sizeof(midi_desc_header_t) == 7, "size is not correct");
/// MIDI In Jack Descriptor
-typedef struct TU_ATTR_PACKED
-{
- uint8_t bLength ; ///< Size of this descriptor in bytes.
- uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
- uint8_t bDescriptorSubType ; ///< Descriptor SubType
- uint8_t bJackType ; ///< Embedded or External
- uint8_t bJackID ; ///< Unique ID for MIDI IN Jack
- uint8_t iJack ; ///< string descriptor
+typedef struct TU_ATTR_PACKED {
+ uint8_t bLength; ///< Size of this descriptor in bytes.
+ uint8_t bDescriptorType; ///< Descriptor Type, must be Class-Specific
+ uint8_t bDescriptorSubType;///< Descriptor SubType
+ uint8_t bJackType; ///< Embedded or External
+ uint8_t bJackID; ///< Unique ID for MIDI IN Jack
+ uint8_t iJack; ///< string descriptor
} midi_desc_in_jack_t;
+TU_VERIFY_STATIC(sizeof(midi_desc_in_jack_t) == 6, "size is not correct");
-
-/// MIDI Out Jack Descriptor with single pin
-typedef struct TU_ATTR_PACKED
-{
- uint8_t bLength ; ///< Size of this descriptor in bytes.
- uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
- uint8_t bDescriptorSubType ; ///< Descriptor SubType
- uint8_t bJackType ; ///< Embedded or External
- uint8_t bJackID ; ///< Unique ID for MIDI IN Jack
- uint8_t bNrInputPins;
-
- uint8_t baSourceID;
- uint8_t baSourcePin;
-
- uint8_t iJack ; ///< string descriptor
-} midi_desc_out_jack_t ;
-
-/// MIDI Out Jack Descriptor with multiple pins
+/// MIDI Out Jack Descriptor with multiple input pins
#define midi_desc_out_jack_n_t(input_num) \
- struct TU_ATTR_PACKED { \
- uint8_t bLength ; \
- uint8_t bDescriptorType ; \
- uint8_t bDescriptorSubType ; \
- uint8_t bJackType ; \
- uint8_t bJackID ; \
- uint8_t bNrInputPins ; \
- struct TU_ATTR_PACKED { \
- uint8_t baSourceID; \
- uint8_t baSourcePin; \
- } pins[input_num]; \
- uint8_t iJack ; \
+ struct TU_ATTR_PACKED { \
+ uint8_t bLength; \
+ uint8_t bDescriptorType; \
+ uint8_t bDescriptorSubType; \
+ uint8_t bJackType; \
+ uint8_t bJackID; \
+ uint8_t bNrInputPins; \
+ struct TU_ATTR_PACKED { \
+ uint8_t baSourceID; \
+ uint8_t baSourcePin; \
+ } input[input_num]; \
+ uint8_t iJack; \
}
-/// MIDI Element Descriptor
-typedef struct TU_ATTR_PACKED
-{
- uint8_t bLength ; ///< Size of this descriptor in bytes.
- uint8_t bDescriptorType ; ///< Descriptor Type, must be Class-Specific
- uint8_t bDescriptorSubType ; ///< Descriptor SubType
- uint8_t bElementID;
-
- uint8_t bNrInputPins;
- uint8_t baSourceID;
- uint8_t baSourcePin;
-
- uint8_t bNrOutputPins;
- uint8_t bInTerminalLink;
- uint8_t bOutTerminalLink;
- uint8_t bElCapsSize;
-
- uint16_t bmElementCaps;
- uint8_t iElement;
-} midi_desc_element_t;
+typedef midi_desc_out_jack_n_t(1) midi_desc_out_jack_1in_t; // 1 input
+typedef midi_desc_out_jack_1in_t midi_desc_out_jack_t; // backward compatible
+TU_VERIFY_STATIC(sizeof(midi_desc_out_jack_1in_t) == 7 + 2 * 1, "size is not correct");
/// MIDI Element Descriptor with multiple pins
#define midi_desc_element_n_t(input_num) \
@@ -201,12 +170,32 @@ typedef struct TU_ATTR_PACKED
uint8_t iElement; \
}
-/** @} */
+// This descriptor follows the standard bulk data endpoint descriptor
+#define midi_desc_cs_endpoint_n_t(jack_num) \
+ struct TU_ATTR_PACKED { \
+ uint8_t bLength; \
+ uint8_t bDescriptorType; \
+ uint8_t bDescriptorSubType; \
+ uint8_t bNumEmbMIDIJack; \
+ uint8_t baAssocJackID[jack_num]; \
+ }
+
+typedef midi_desc_cs_endpoint_n_t() midi_desc_cs_endpoint_t; // empty/flexible jack list
+typedef midi_desc_cs_endpoint_n_t(1) midi_desc_cs_endpoint_1jack_t;
+
+TU_VERIFY_STATIC(sizeof(midi_desc_cs_endpoint_1jack_t) == 4+1, "size is not correct");
+
+//--------------------------------------------------------------------+
+// For Internal Driver Use
+//--------------------------------------------------------------------+
+typedef struct {
+ uint8_t buffer[4];
+ uint8_t index;
+ uint8_t total;
+} midi_driver_stream_t;
#ifdef __cplusplus
}
#endif
#endif
-
-/** @} */
diff --git a/src/class/midi/midi_device.c b/src/class/midi/midi_device.c
index c545f8287..0bbb3caf4 100644
--- a/src/class/midi/midi_device.c
+++ b/src/class/midi/midi_device.c
@@ -39,13 +39,6 @@
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
-
-typedef struct {
- uint8_t buffer[4];
- uint8_t index;
- uint8_t total;
-} midid_stream_t;
-
typedef struct {
uint8_t itf_num;
uint8_t ep_in;
@@ -54,8 +47,8 @@ typedef struct {
// For Stream read()/write() API
// Messages are always 4 bytes long, queue them for reading and writing so the
// callers can use the Stream interface with single-byte read/write calls.
- midid_stream_t stream_write;
- midid_stream_t stream_read;
+ midi_driver_stream_t stream_write;
+ midi_driver_stream_t stream_read;
/*------------- From this point, data is not cleared by bus reset -------------*/
// FIFO
@@ -122,7 +115,7 @@ uint32_t tud_midi_n_available(uint8_t itf, uint8_t cable_num)
(void) cable_num;
midid_interface_t* midi = &_midid_itf[itf];
- const midid_stream_t* stream = &midi->stream_read;
+ const midi_driver_stream_t* stream = &midi->stream_read;
// when using with packet API stream total & index are both zero
return tu_fifo_count(&midi->rx_ff) + (uint8_t) (stream->total - stream->index);
@@ -136,7 +129,7 @@ uint32_t tud_midi_n_stream_read(uint8_t itf, uint8_t cable_num, void* buffer, ui
uint8_t* buf8 = (uint8_t*) buffer;
midid_interface_t* midi = &_midid_itf[itf];
- midid_stream_t* stream = &midi->stream_read;
+ midi_driver_stream_t* stream = &midi->stream_read;
uint32_t total_read = 0;
while( bufsize )
@@ -241,7 +234,7 @@ uint32_t tud_midi_n_stream_write(uint8_t itf, uint8_t cable_num, const uint8_t*
midid_interface_t* midi = &_midid_itf[itf];
TU_VERIFY(midi->ep_in, 0);
- midid_stream_t* stream = &midi->stream_write;
+ midi_driver_stream_t* stream = &midi->stream_write;
uint32_t i = 0;
while ( (i < bufsize) && (tu_fifo_remaining(&midi->tx_ff) >= 4) )
@@ -429,21 +422,21 @@ void midid_reset(uint8_t rhport)
}
}
-uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint16_t max_len)
-{
- // 1st Interface is Audio Control v1
- TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass &&
- AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass &&
- AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol, 0);
+uint16_t midid_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint16_t max_len) {
+ uint16_t drv_len = 0;
+ uint8_t const * p_desc = (uint8_t const *)desc_itf;
- uint16_t drv_len = tu_desc_len(desc_itf);
- const uint8_t* p_desc = tu_desc_next(desc_itf);
-
- // Skip Class Specific descriptors
- while ( TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len )
- {
- drv_len += tu_desc_len(p_desc);
- p_desc = tu_desc_next(p_desc);
+ // 1st Interface is Audio Control v1 (optional)
+ if (TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass &&
+ AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass &&
+ AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) {
+ drv_len = tu_desc_len(desc_itf);
+ p_desc = tu_desc_next(desc_itf);
+ // Skip Class Specific descriptors
+ while (TUSB_DESC_CS_INTERFACE == tu_desc_type(p_desc) && drv_len <= max_len) {
+ drv_len += tu_desc_len(p_desc);
+ p_desc = tu_desc_next(p_desc);
+ }
}
// 2nd Interface is MIDI Streaming
diff --git a/src/class/midi/midi_host.c b/src/class/midi/midi_host.c
new file mode 100644
index 000000000..cd6e115ee
--- /dev/null
+++ b/src/class/midi/midi_host.c
@@ -0,0 +1,622 @@
+/*
+ * 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 "tusb_option.h"
+
+#if (CFG_TUH_ENABLED && CFG_TUH_MIDI)
+
+#include "host/usbh.h"
+#include "host/usbh_pvt.h"
+
+#include "midi_host.h"
+
+// Level where CFG_TUSB_DEBUG must be at least for this driver is logged
+#ifndef CFG_TUH_MIDI_LOG_LEVEL
+ #define CFG_TUH_MIDI_LOG_LEVEL CFG_TUH_LOG_LEVEL
+#endif
+
+#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_MIDI_LOG_LEVEL, __VA_ARGS__)
+
+//--------------------------------------------------------------------+
+// Weak stubs: invoked if no strong implementation is available
+//--------------------------------------------------------------------+
+TU_ATTR_WEAK void tuh_midi_descriptor_cb(uint8_t idx, const tuh_midi_descriptor_cb_t * desc_cb_data) { (void) idx; (void) desc_cb_data; }
+TU_ATTR_WEAK void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t* mount_cb_data) { (void) idx; (void) mount_cb_data; }
+TU_ATTR_WEAK void tuh_midi_umount_cb(uint8_t idx) { (void) idx; }
+TU_ATTR_WEAK void tuh_midi_rx_cb(uint8_t idx, uint32_t xferred_bytes) { (void) idx; (void) xferred_bytes; }
+TU_ATTR_WEAK void tuh_midi_tx_cb(uint8_t idx, uint32_t xferred_bytes) { (void) idx; (void) xferred_bytes; }
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF
+//--------------------------------------------------------------------+
+
+typedef struct {
+ uint8_t daddr;
+ uint8_t bInterfaceNumber; // interface number of MIDI streaming
+ uint8_t iInterface;
+ uint8_t itf_count; // number of interface including Audio Control + MIDI streaming
+
+ uint8_t ep_in; // IN endpoint address
+ uint8_t ep_out; // OUT endpoint address
+
+ uint8_t rx_cable_count; // IN endpoint CS descriptor bNumEmbMIDIJack value
+ uint8_t tx_cable_count; // OUT endpoint CS descriptor bNumEmbMIDIJack value
+
+ #if CFG_TUH_MIDI_STREAM_API
+ // For Stream read()/write() API
+ // Messages are always 4 bytes long, queue them for reading and writing so the
+ // callers can use the Stream interface with single-byte read/write calls.
+ midi_driver_stream_t stream_write;
+ midi_driver_stream_t stream_read;
+ #endif
+
+ // Endpoint stream
+ struct {
+ tu_edpt_stream_t tx;
+ tu_edpt_stream_t rx;
+
+ uint8_t rx_ff_buf[CFG_TUH_MIDI_RX_BUFSIZE];
+ uint8_t tx_ff_buf[CFG_TUH_MIDI_TX_BUFSIZE];
+ } ep_stream;
+
+ bool mounted;
+}midih_interface_t;
+
+typedef struct {
+ TUH_EPBUF_DEF(tx, TUH_EPSIZE_BULK_MPS);
+ TUH_EPBUF_DEF(rx, TUH_EPSIZE_BULK_MPS);
+} midih_epbuf_t;
+
+static midih_interface_t _midi_host[CFG_TUH_MIDI];
+CFG_TUH_MEM_SECTION static midih_epbuf_t _midi_epbuf[CFG_TUH_MIDI];
+
+//--------------------------------------------------------------------+
+// Helper
+//--------------------------------------------------------------------+
+TU_ATTR_ALWAYS_INLINE static inline uint8_t find_new_midi_index(void) {
+ for (uint8_t idx = 0; idx < CFG_TUH_MIDI; idx++) {
+ if (_midi_host[idx].daddr == 0) {
+ return idx;
+ }
+ }
+ return TUSB_INDEX_INVALID_8;
+}
+
+static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr) {
+ for (uint8_t idx = 0; idx < CFG_TUH_MIDI; idx++) {
+ const midih_interface_t *p_midi = &_midi_host[idx];
+ if ((p_midi->daddr == daddr) &&
+ (ep_addr == p_midi->ep_stream.rx.ep_addr || ep_addr == p_midi->ep_stream.tx.ep_addr)) {
+ return idx;
+ }
+ }
+ return TUSB_INDEX_INVALID_8;
+}
+
+//--------------------------------------------------------------------+
+// USBH API
+//--------------------------------------------------------------------+
+bool midih_init(void) {
+ tu_memclr(&_midi_host, sizeof(_midi_host));
+ for (int inst = 0; inst < CFG_TUH_MIDI; inst++) {
+ midih_interface_t *p_midi_host = &_midi_host[inst];
+ tu_edpt_stream_init(&p_midi_host->ep_stream.rx, true, false, false,
+ p_midi_host->ep_stream.rx_ff_buf, CFG_TUH_MIDI_RX_BUFSIZE, _midi_epbuf->rx, TUH_EPSIZE_BULK_MPS);
+ tu_edpt_stream_init(&p_midi_host->ep_stream.tx, true, true, false,
+ p_midi_host->ep_stream.tx_ff_buf, CFG_TUH_MIDI_TX_BUFSIZE, _midi_epbuf->tx, TUH_EPSIZE_BULK_MPS);
+ }
+ return true;
+}
+
+bool midih_deinit(void) {
+ for (size_t i = 0; i < CFG_TUH_MIDI; i++) {
+ midih_interface_t* p_midi = &_midi_host[i];
+ tu_edpt_stream_deinit(&p_midi->ep_stream.rx);
+ tu_edpt_stream_deinit(&p_midi->ep_stream.tx);
+ }
+ return true;
+}
+
+void midih_close(uint8_t daddr) {
+ for (uint8_t idx = 0; idx < CFG_TUH_MIDI; idx++) {
+ midih_interface_t* p_midi = &_midi_host[idx];
+ if (p_midi->daddr == daddr) {
+ TU_LOG_DRV(" MIDI close addr = %u index = %u\r\n", daddr, idx);
+ tuh_midi_umount_cb(idx);
+
+ p_midi->ep_in = 0;
+ p_midi->ep_out = 0;
+ p_midi->bInterfaceNumber = 0;
+ p_midi->rx_cable_count = 0;
+ p_midi->tx_cable_count = 0;
+ p_midi->daddr = 0;
+ p_midi->mounted = false;
+#if CFG_TUH_MIDI_STREAM_API
+ tu_memclr(&p_midi->stream_read, sizeof(p_midi->stream_read));
+ tu_memclr(&p_midi->stream_write, sizeof(p_midi->stream_write));
+#endif
+ tu_edpt_stream_close(&p_midi->ep_stream.rx);
+ tu_edpt_stream_close(&p_midi->ep_stream.tx);
+ }
+ }
+}
+
+bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
+ (void) result;
+ const uint8_t idx = get_idx_by_ep_addr(dev_addr, ep_addr);
+ TU_VERIFY(idx < CFG_TUH_MIDI);
+ midih_interface_t *p_midi = &_midi_host[idx];
+
+ if (ep_addr == p_midi->ep_stream.rx.ep_addr) {
+ // receive new data, put it into FIFO and invoke callback if available
+ // Note: some devices send back all zero packets even if there is no data ready
+ if (xferred_bytes && !tu_mem_is_zero(p_midi->ep_stream.rx.ep_buf, xferred_bytes)) {
+ tu_edpt_stream_read_xfer_complete(&p_midi->ep_stream.rx, xferred_bytes);
+ tuh_midi_rx_cb(idx, xferred_bytes);
+ }
+
+ tu_edpt_stream_read_xfer(dev_addr, &p_midi->ep_stream.rx); // prepare for next transfer
+ } else if (ep_addr == p_midi->ep_stream.tx.ep_addr) {
+ tuh_midi_tx_cb(idx, xferred_bytes);
+
+ if (0 == tu_edpt_stream_write_xfer(dev_addr, &p_midi->ep_stream.tx)) {
+ // If there is no data left, a ZLP should be sent if
+ // xferred_bytes is multiple of EP size and not zero
+ tu_edpt_stream_write_zlp_if_needed(dev_addr, &p_midi->ep_stream.tx, xferred_bytes);
+ }
+ }
+
+ return true;
+}
+
+//--------------------------------------------------------------------+
+// Enumeration
+//--------------------------------------------------------------------+
+bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) {
+ (void) rhport;
+
+ TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass);
+ const uint8_t *p_end = ((const uint8_t *) desc_itf) + max_len;
+ const uint8_t *p_desc = (const uint8_t *) desc_itf;
+
+ const uint8_t idx = find_new_midi_index();
+ TU_VERIFY(idx < CFG_TUH_MIDI);
+ midih_interface_t *p_midi = &_midi_host[idx];
+ p_midi->itf_count = 0;
+
+ tuh_midi_descriptor_cb_t desc_cb = { 0 };
+ desc_cb.jack_num = 0;
+
+ // There can be just a MIDI or an Audio + MIDI interface
+ // If there is Audio Control Interface + Audio Header descriptor, skip it
+ if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) {
+ TU_VERIFY(max_len > 2*sizeof(tusb_desc_interface_t) + sizeof(audio_desc_cs_ac_interface_t));
+
+ p_desc = tu_desc_next(p_desc);
+ TU_VERIFY(tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE &&
+ tu_desc_subtype(p_desc) == AUDIO_CS_AC_INTERFACE_HEADER);
+ desc_cb.desc_audio_control = desc_itf;
+
+ p_desc = tu_desc_next(p_desc);
+ desc_itf = (const tusb_desc_interface_t *)p_desc;
+ TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass);
+ p_midi->itf_count = 1;
+ }
+ TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == desc_itf->bInterfaceSubClass);
+
+ TU_LOG_DRV("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr);
+ p_midi->bInterfaceNumber = desc_itf->bInterfaceNumber;
+ p_midi->iInterface = desc_itf->iInterface;
+ p_midi->itf_count++;
+ desc_cb.desc_midi = desc_itf;
+
+ p_desc = tu_desc_next(p_desc); // next to CS Header
+
+ bool found_new_interface = false;
+ while ((p_desc < p_end) && (tu_desc_next(p_desc) <= p_end) && !found_new_interface) {
+ switch (tu_desc_type(p_desc)) {
+ case TUSB_DESC_INTERFACE:
+ found_new_interface = true;
+ break;
+
+ case TUSB_DESC_CS_INTERFACE:
+ switch (tu_desc_subtype(p_desc)) {
+ case MIDI_CS_INTERFACE_HEADER:
+ TU_LOG_DRV(" Interface Header descriptor\r\n");
+ desc_cb.desc_header = p_desc;
+ break;
+
+ case MIDI_CS_INTERFACE_IN_JACK:
+ case MIDI_CS_INTERFACE_OUT_JACK: {
+ TU_LOG_DRV(" Jack %s %s descriptor \r\n",
+ tu_desc_subtype(p_desc) == MIDI_CS_INTERFACE_IN_JACK ? "IN" : "OUT",
+ p_desc[3] == MIDI_JACK_EXTERNAL ? "External" : "Embedded");
+ if (desc_cb.jack_num < TU_ARRAY_SIZE(desc_cb.desc_jack)) {
+ desc_cb.desc_jack[desc_cb.jack_num++] = p_desc;
+ }
+ break;
+ }
+
+ case MIDI_CS_INTERFACE_ELEMENT:
+ TU_LOG_DRV(" Element descriptor\r\n");
+ desc_cb.desc_element = p_desc;
+ break;
+
+ default:
+ TU_LOG_DRV(" Unknown CS Interface sub-type %u\r\n", tu_desc_subtype(p_desc));
+ break;
+ }
+ break;
+
+ case TUSB_DESC_ENDPOINT: {
+ const tusb_desc_endpoint_t *p_ep = (const tusb_desc_endpoint_t *) p_desc;
+ p_desc = tu_desc_next(p_desc); // next to CS endpoint
+ TU_VERIFY(p_desc < p_end && tu_desc_next(p_desc) <= p_end);
+ const midi_desc_cs_endpoint_t *p_csep = (const midi_desc_cs_endpoint_t *) p_desc;
+
+ TU_LOG_DRV(" Endpoint and CS_Endpoint descriptor %02x\r\n", p_ep->bEndpointAddress);
+ if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) {
+ p_midi->ep_out = p_ep->bEndpointAddress;
+ p_midi->tx_cable_count = p_csep->bNumEmbMIDIJack;
+ desc_cb.desc_epout = p_ep;
+
+ TU_ASSERT(tuh_edpt_open(dev_addr, p_ep));
+ tu_edpt_stream_open(&p_midi->ep_stream.tx, p_ep);
+ } else {
+ p_midi->ep_in = p_ep->bEndpointAddress;
+ p_midi->rx_cable_count = p_csep->bNumEmbMIDIJack;
+ desc_cb.desc_epin = p_ep;
+
+ TU_ASSERT(tuh_edpt_open(dev_addr, p_ep));
+ tu_edpt_stream_open(&p_midi->ep_stream.rx, p_ep);
+ }
+ break;
+ }
+
+ default: break; // skip unknown descriptor
+ }
+ p_desc = tu_desc_next(p_desc);
+ }
+ desc_cb.desc_midi_total_len = (uint16_t) ((uintptr_t)p_desc - (uintptr_t) desc_itf);
+
+ p_midi->daddr = dev_addr;
+ tuh_midi_descriptor_cb(idx, &desc_cb);
+
+ return true;
+}
+
+bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) {
+ uint8_t idx = tuh_midi_itf_get_index(dev_addr, itf_num);
+ TU_ASSERT(idx < CFG_TUH_MIDI);
+ midih_interface_t *p_midi = &_midi_host[idx];
+ p_midi->mounted = true;
+
+ const tuh_midi_mount_cb_t mount_cb_data = {
+ .daddr = dev_addr,
+ .bInterfaceNumber = itf_num,
+ .rx_cable_count = p_midi->rx_cable_count,
+ .tx_cable_count = p_midi->tx_cable_count,
+ };
+ tuh_midi_mount_cb(idx, &mount_cb_data);
+
+ tu_edpt_stream_read_xfer(dev_addr, &p_midi->ep_stream.rx); // prepare for incoming data
+
+ // No special config things to do for MIDI
+ usbh_driver_set_config_complete(dev_addr, p_midi->bInterfaceNumber);
+ return true;
+}
+
+//--------------------------------------------------------------------+
+// API
+//--------------------------------------------------------------------+
+bool tuh_midi_mounted(uint8_t idx) {
+ TU_VERIFY(idx < CFG_TUH_MIDI);
+ midih_interface_t *p_midi = &_midi_host[idx];
+ return p_midi->mounted;
+}
+
+uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num) {
+ for (uint8_t idx = 0; idx < CFG_TUH_MIDI; idx++) {
+ const midih_interface_t *p_midi = &_midi_host[idx];
+ if (p_midi->daddr == daddr &&
+ (p_midi->bInterfaceNumber == itf_num ||
+ p_midi->bInterfaceNumber == (uint8_t) (itf_num + p_midi->itf_count - 1))) {
+ return idx;
+ }
+ }
+ return TUSB_INDEX_INVALID_8;
+}
+
+bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info) {
+ midih_interface_t* p_midi = &_midi_host[idx];
+ TU_VERIFY(p_midi && info);
+
+ info->daddr = p_midi->daddr;
+
+ // re-construct descriptor
+ tusb_desc_interface_t* desc = &info->desc;
+ desc->bLength = sizeof(tusb_desc_interface_t);
+ desc->bDescriptorType = TUSB_DESC_INTERFACE;
+
+ desc->bInterfaceNumber = p_midi->bInterfaceNumber;
+ desc->bAlternateSetting = 0;
+ desc->bNumEndpoints = (uint8_t)((p_midi->ep_in != 0 ? 1:0) + (p_midi->ep_out != 0 ? 1:0));
+ desc->bInterfaceClass = TUSB_CLASS_AUDIO;
+ desc->bInterfaceSubClass = AUDIO_SUBCLASS_MIDI_STREAMING;
+ desc->bInterfaceProtocol = 0;
+ desc->iInterface = p_midi->iInterface;
+
+ return true;
+}
+
+uint8_t tuh_midi_get_tx_cable_count (uint8_t idx) {
+ TU_VERIFY(idx < CFG_TUH_MIDI);
+ midih_interface_t *p_midi = &_midi_host[idx];
+ TU_VERIFY(p_midi->ep_stream.tx.ep_addr != 0, 0);
+ return p_midi->tx_cable_count;
+}
+
+uint8_t tuh_midi_get_rx_cable_count (uint8_t idx) {
+ TU_VERIFY(idx < CFG_TUH_MIDI);
+ midih_interface_t *p_midi = &_midi_host[idx];
+ TU_VERIFY(p_midi->ep_stream.rx.ep_addr != 0, 0);
+ return p_midi->rx_cable_count;
+}
+
+uint32_t tuh_midi_read_available(uint8_t idx) {
+ TU_VERIFY(idx < CFG_TUH_MIDI);
+ midih_interface_t *p_midi = &_midi_host[idx];
+ return tu_edpt_stream_read_available(&p_midi->ep_stream.rx);
+}
+
+uint32_t tuh_midi_write_flush(uint8_t idx) {
+ TU_VERIFY(idx < CFG_TUH_MIDI);
+ midih_interface_t *p_midi = &_midi_host[idx];
+ return tu_edpt_stream_write_xfer(p_midi->daddr, &p_midi->ep_stream.tx);
+}
+
+//--------------------------------------------------------------------+
+// Packet API
+//--------------------------------------------------------------------+
+uint32_t tuh_midi_packet_read_n(uint8_t idx, uint8_t* buffer, uint32_t bufsize) {
+ TU_VERIFY(idx < CFG_TUH_MIDI && buffer && bufsize > 0, 0);
+ midih_interface_t *p_midi = &_midi_host[idx];
+
+ uint32_t count4 = tu_min32(bufsize, tu_edpt_stream_read_available(&p_midi->ep_stream.rx));
+ count4 = tu_align4(count4); // round down to multiple of 4
+ TU_VERIFY(count4 > 0, 0);
+ return tu_edpt_stream_read(p_midi->daddr, &p_midi->ep_stream.rx, buffer, count4);
+}
+
+uint32_t tuh_midi_packet_write_n(uint8_t idx, const uint8_t* buffer, uint32_t bufsize) {
+ TU_VERIFY(idx < CFG_TUH_MIDI && buffer && bufsize > 0, 0);
+ midih_interface_t *p_midi = &_midi_host[idx];
+
+ const uint32_t bufsize4 = tu_align4(bufsize);
+ TU_VERIFY(bufsize4 > 0, 0);
+ return tu_edpt_stream_write(p_midi->daddr, &p_midi->ep_stream.tx, buffer, bufsize4);
+}
+
+//--------------------------------------------------------------------+
+// Stream API
+//--------------------------------------------------------------------+
+#if CFG_TUH_MIDI_STREAM_API
+uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *buffer, uint32_t bufsize) {
+ TU_VERIFY(idx < CFG_TUH_MIDI && buffer && bufsize > 0);
+ midih_interface_t *p_midi = &_midi_host[idx];
+ TU_VERIFY(cable_num < p_midi->tx_cable_count);
+ midi_driver_stream_t *stream = &p_midi->stream_write;
+
+ uint32_t byte_count = 0;
+ while ((byte_count < bufsize) && (tu_edpt_stream_write_available(p_midi->daddr, &p_midi->ep_stream.tx) >= 4)) {
+ uint8_t const data = buffer[byte_count];
+ byte_count++;
+ if (data >= MIDI_STATUS_SYSREAL_TIMING_CLOCK) {
+ // real-time messages need to be sent right away
+ midi_driver_stream_t streamrt;
+ streamrt.buffer[0] = MIDI_CIN_SYSEX_END_1BYTE;
+ streamrt.buffer[1] = data;
+ streamrt.index = 2;
+ streamrt.total = 2;
+ uint32_t const count = tu_edpt_stream_write(p_midi->daddr, &p_midi->ep_stream.tx, streamrt.buffer, 4);
+ TU_ASSERT(count == 4, byte_count); // Check FIFO overflown, since we already check fifo remaining. It is probably race condition
+ } else if (stream->index == 0) {
+ //------------- New event packet -------------//
+
+ uint8_t const msg = data >> 4;
+
+ stream->index = 2;
+ stream->buffer[1] = data;
+
+ // Check to see if we're still in a SysEx transmit.
+ if (stream->buffer[0] == MIDI_CIN_SYSEX_START) {
+ if (data == MIDI_STATUS_SYSEX_END) {
+ stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE;
+ stream->total = 2;
+ } else {
+ stream->total = 4;
+ }
+ } else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) {
+ // Channel Voice Messages
+ stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg);
+ stream->total = 4;
+ } else if (msg == 0xC || msg == 0xD) {
+ // Channel Voice Messages, two-byte variants (Program Change and Channel Pressure)
+ stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg);
+ stream->total = 3;
+ } else if (msg == 0xf) {
+ // System message
+ if (data == MIDI_STATUS_SYSEX_START) {
+ stream->buffer[0] = MIDI_CIN_SYSEX_START;
+ stream->total = 4;
+ } else if (data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT) {
+ stream->buffer[0] = MIDI_CIN_SYSCOM_2BYTE;
+ stream->total = 3;
+ } else if (data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER) {
+ stream->buffer[0] = MIDI_CIN_SYSCOM_3BYTE;
+ stream->total = 4;
+ } else {
+ stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE;
+ stream->total = 2;
+ }
+ } else {
+ // Pack individual bytes if we don't support packing them into words.
+ stream->buffer[0] = (uint8_t) (cable_num << 4 | 0xf);
+ stream->buffer[2] = 0;
+ stream->buffer[3] = 0;
+ stream->index = 2;
+ stream->total = 2;
+ }
+ } else {
+ //------------- On-going (buffering) packet -------------//
+ TU_ASSERT(stream->index < 4, byte_count);
+ stream->buffer[stream->index] = data;
+ stream->index++;
+ // See if this byte ends a SysEx.
+ if (stream->buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END) {
+ stream->buffer[0] = MIDI_CIN_SYSEX_START + (stream->index - 1);
+ stream->total = stream->index;
+ }
+ }
+
+ // Send out packet
+ if (stream->index >= 2 && stream->index == stream->total) {
+ // zeroes unused bytes
+ for (uint8_t i = stream->total; i < 4; i++) {
+ stream->buffer[i] = 0;
+ }
+ TU_LOG3_MEM(stream->buffer, 4, 2);
+
+ const uint32_t count = tu_edpt_stream_write(p_midi->daddr, &p_midi->ep_stream.tx, stream->buffer, 4);
+
+ // complete current event packet, reset stream
+ stream->index = 0;
+ stream->total = 0;
+
+ // FIFO overflown, since we already check fifo remaining. It is probably race condition
+ TU_ASSERT(count == 4, byte_count);
+ }
+ }
+ return byte_count;
+}
+
+uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize) {
+ TU_VERIFY(idx < CFG_TUH_MIDI && p_cable_num && p_buffer && bufsize > 0);
+ midih_interface_t *p_midi = &_midi_host[idx];
+ uint32_t bytes_buffered = 0;
+ uint8_t one_byte;
+ if (!tu_edpt_stream_peek(&p_midi->ep_stream.rx, &one_byte)) {
+ return 0;
+ }
+ *p_cable_num = (one_byte >> 4) & 0xf;
+ uint32_t nread = tu_edpt_stream_read(p_midi->daddr, &p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4);
+ static uint16_t cable_sysex_in_progress;// bit i is set if received MIDI_STATUS_SYSEX_START but not MIDI_STATUS_SYSEX_END
+ while (nread == 4 && bytes_buffered < bufsize) {
+ *p_cable_num = (p_midi->stream_read.buffer[0] >> 4) & 0x0f;
+ uint8_t bytes_to_add_to_stream = 0;
+ if (*p_cable_num < p_midi->rx_cable_count) {
+ // ignore the CIN field; too many devices out there encode this wrong
+ uint8_t status = p_midi->stream_read.buffer[1];
+ uint16_t cable_mask = (uint16_t) (1 << *p_cable_num);
+ if (status <= MIDI_MAX_DATA_VAL || status == MIDI_STATUS_SYSEX_START) {
+ if (status == MIDI_STATUS_SYSEX_START) {
+ cable_sysex_in_progress |= cable_mask;
+ }
+ // only add the packet if a sysex message is in progress
+ if (cable_sysex_in_progress & cable_mask) {
+ ++bytes_to_add_to_stream;
+ for (uint8_t i = 2; i < 4; i++) {
+ if (p_midi->stream_read.buffer[i] <= MIDI_MAX_DATA_VAL) {
+ ++bytes_to_add_to_stream;
+ } else if (p_midi->stream_read.buffer[i] == MIDI_STATUS_SYSEX_END) {
+ ++bytes_to_add_to_stream;
+ cable_sysex_in_progress &= (uint16_t) ~cable_mask;
+ i = 4;// force the loop to exit; I hate break statements in loops
+ }
+ }
+ }
+ } else if (status < MIDI_STATUS_SYSEX_START) {
+ // then it is a channel message either three bytes or two
+ uint8_t fake_cin = (status & 0xf0) >> 4;
+ switch (fake_cin) {
+ case MIDI_CIN_NOTE_OFF:
+ case MIDI_CIN_NOTE_ON:
+ case MIDI_CIN_POLY_KEYPRESS:
+ case MIDI_CIN_CONTROL_CHANGE:
+ case MIDI_CIN_PITCH_BEND_CHANGE:
+ bytes_to_add_to_stream = 3;
+ break;
+ case MIDI_CIN_PROGRAM_CHANGE:
+ case MIDI_CIN_CHANNEL_PRESSURE:
+ bytes_to_add_to_stream = 2;
+ break;
+ default:
+ break;// Should not get this
+ }
+ cable_sysex_in_progress &= (uint16_t) ~cable_mask;
+ } else if (status < MIDI_STATUS_SYSREAL_TIMING_CLOCK) {
+ switch (status) {
+ case MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME:
+ case MIDI_STATUS_SYSCOM_SONG_SELECT:
+ bytes_to_add_to_stream = 2;
+ break;
+ case MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER:
+ bytes_to_add_to_stream = 3;
+ break;
+ case MIDI_STATUS_SYSCOM_TUNE_REQUEST:
+ case MIDI_STATUS_SYSEX_END:
+ bytes_to_add_to_stream = 1;
+ break;
+ default:
+ break;
+ }
+ cable_sysex_in_progress &= (uint16_t) ~cable_mask;
+ } else {
+ // Real-time message: can be inserted into a sysex message,
+ // so do don't clear cable_sysex_in_progress bit
+ bytes_to_add_to_stream = 1;
+ }
+ }
+
+ for (uint8_t i = 1; i <= bytes_to_add_to_stream; i++) {
+ *p_buffer++ = p_midi->stream_read.buffer[i];
+ }
+ bytes_buffered += bytes_to_add_to_stream;
+ nread = 0;
+ if (tu_edpt_stream_peek(&p_midi->ep_stream.rx, &one_byte)) {
+ uint8_t new_cable = (one_byte >> 4) & 0xf;
+ if (new_cable == *p_cable_num) {
+ // still on the same cable. Continue reading the stream
+ nread = tu_edpt_stream_read(p_midi->daddr, &p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4);
+ }
+ }
+ }
+
+ return bytes_buffered;
+}
+#endif
+
+#endif
diff --git a/src/class/midi/midi_host.h b/src/class/midi/midi_host.h
new file mode 100644
index 000000000..06554a03d
--- /dev/null
+++ b/src/class/midi/midi_host.h
@@ -0,0 +1,193 @@
+/*
+ * 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.
+ */
+
+#ifndef TUSB_MIDI_HOST_H_
+#define TUSB_MIDI_HOST_H_
+
+#include "class/audio/audio.h"
+#include "midi.h"
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//--------------------------------------------------------------------+
+// Class Driver Configuration
+//--------------------------------------------------------------------+
+#ifndef CFG_TUH_MIDI_RX_BUFSIZE
+#define CFG_TUH_MIDI_RX_BUFSIZE TUH_EPSIZE_BULK_MPS
+#endif
+
+#ifndef CFG_TUH_MIDI_TX_BUFSIZE
+#define CFG_TUH_MIDI_TX_BUFSIZE TUH_EPSIZE_BULK_MPS
+#endif
+
+#ifndef CFG_TUH_MIDI_EP_BUFSIZE
+#define CFG_TUH_MIDI_EP_BUFSIZE TUH_EPSIZE_BULK_MPS
+#endif
+
+// Enable the MIDI stream read/write API. Some library can work with raw USB MIDI packet
+// Disable this can save driver footprint.
+#ifndef CFG_TUH_MIDI_STREAM_API
+#define CFG_TUH_MIDI_STREAM_API 1
+#endif
+
+//--------------------------------------------------------------------+
+// Application Types
+//--------------------------------------------------------------------+
+typedef struct {
+ const tusb_desc_interface_t* desc_audio_control;
+ const tusb_desc_interface_t* desc_midi; // start of whole midi interface descriptor
+ uint16_t desc_midi_total_len;
+
+ const uint8_t* desc_header;
+ const uint8_t* desc_element;
+ const tusb_desc_endpoint_t* desc_epin; // endpoint IN descriptor, CS_ENDPOINT is right after
+ const tusb_desc_endpoint_t* desc_epout; // endpoint OUT descriptor, CS_ENDPOINT is right after
+
+ uint8_t jack_num;
+ const uint8_t* desc_jack[32]; // list of jack descriptors (embedded + external)
+} tuh_midi_descriptor_cb_t;
+
+typedef struct {
+ uint8_t daddr;
+ uint8_t bInterfaceNumber; // interface number of MIDI streaming
+ uint8_t rx_cable_count;
+ uint8_t tx_cable_count;
+} tuh_midi_mount_cb_t;
+
+//--------------------------------------------------------------------+
+// Application API
+//--------------------------------------------------------------------+
+
+// Check if MIDI interface is mounted
+bool tuh_midi_mounted(uint8_t idx);
+
+// Get Interface index from device address + interface number
+// return TUSB_INDEX_INVALID_8 (0xFF) if not found
+uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num);
+
+// Get Interface information
+// return true if index is correct and interface is currently mounted
+bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info);
+
+// return the number of virtual midi cables on the device's IN endpoint
+uint8_t tuh_midi_get_rx_cable_count(uint8_t idx);
+
+// return the number of virtual midi cables on the device's OUT endpoint
+uint8_t tuh_midi_get_tx_cable_count(uint8_t idx);
+
+// return the raw number of bytes available.
+// Note: this is related but not the same as number of stream bytes available.
+uint32_t tuh_midi_read_available(uint8_t idx);
+
+// Send any queued packets to the device if the host hardware is able to do it
+// Returns the number of bytes flushed to the host hardware or 0 if
+// the host hardware is busy or there is nothing in queue to send.
+uint32_t tuh_midi_write_flush(uint8_t idx);
+
+//--------------------------------------------------------------------+
+// Packet API
+//--------------------------------------------------------------------+
+
+// Read all available MIDI packets from the connected device
+// Return number of bytes read (always multiple of 4)
+uint32_t tuh_midi_packet_read_n(uint8_t idx, uint8_t* buffer, uint32_t bufsize);
+
+// Read a raw MIDI packet from the connected device
+// Return true if a packet was returned
+TU_ATTR_ALWAYS_INLINE static inline
+bool tuh_midi_packet_read (uint8_t idx, uint8_t packet[4]) {
+ return 4 == tuh_midi_packet_read_n(idx, packet, 4);
+}
+
+// Write all 4-byte packets, data is locally buffered and only transferred when buffered bytes
+// reach the endpoint packet size or tuh_midi_write_flush() is called
+uint32_t tuh_midi_packet_write_n(uint8_t idx, const uint8_t* buffer, uint32_t bufsize);
+
+// Write a 4-bytes packet to the device.
+// Returns true if the packet was successfully queued.
+TU_ATTR_ALWAYS_INLINE static inline
+bool tuh_midi_packet_write (uint8_t idx, uint8_t const packet[4]) {
+ return 4 == tuh_midi_packet_write_n(idx, packet, 4);
+}
+
+//--------------------------------------------------------------------+
+// Stream API
+//--------------------------------------------------------------------+
+#if CFG_TUH_MIDI_STREAM_API
+
+// Queue a message to the device using stream API. data is locally buffered and only transferred when buffered bytes
+// reach the endpoint packet size or tuh_midi_write_flush() is called
+// Returns number of bytes was successfully queued.
+uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *p_buffer, uint32_t bufsize);
+
+// Get the MIDI stream from the device. Set the value pointed
+// to by p_cable_num to the MIDI cable number intended to receive it.
+// The MIDI stream will be stored in the buffer pointed to by p_buffer.
+// Return the number of bytes added to the buffer.
+// Note that this function ignores the CIN field of the MIDI packet
+// because a number of commercial devices out there do not encode
+// it properly.
+uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize);
+
+#endif
+
+//--------------------------------------------------------------------+
+// Callbacks (Weak is optional)
+//--------------------------------------------------------------------+
+
+// Invoked when MIDI interface is detected in enumeration. Application can copy/parse descriptor if needed.
+// Note: may be fired before tuh_midi_mount_cb(), therefore midi interface is not mounted/ready.
+void tuh_midi_descriptor_cb(uint8_t idx, const tuh_midi_descriptor_cb_t * desc_cb_data);
+
+// Invoked when device with MIDI interface is mounted.
+void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t* mount_cb_data);
+
+// Invoked when device with MIDI interface is un-mounted
+void tuh_midi_umount_cb(uint8_t idx);
+
+// Invoked when received new data
+void tuh_midi_rx_cb(uint8_t idx, uint32_t xferred_bytes);
+
+// Invoked when a TX is complete and therefore space becomes available in TX buffer
+void tuh_midi_tx_cb(uint8_t idx, uint32_t xferred_bytes);
+
+//--------------------------------------------------------------------+
+// Internal Class Driver API
+//--------------------------------------------------------------------+
+bool midih_init (void);
+bool midih_deinit (void);
+bool midih_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len);
+bool midih_set_config (uint8_t dev_addr, uint8_t itf_num);
+bool midih_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes);
+void midih_close (uint8_t daddr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/class/msc/msc_device.c b/src/class/msc/msc_device.c
index 72c3747fc..2a497d0e7 100644
--- a/src/class/msc/msc_device.c
+++ b/src/class/msc/msc_device.c
@@ -202,7 +202,7 @@ static bool proc_stage_status(mscd_interface_t* p_msc) {
if (!usbd_edpt_stalled(rhport, p_msc->ep_in)) {
if ((p_cbw->total_bytes > p_msc->xferred_len) && is_data_in(p_cbw->dir)) {
// 6.7 The 13 Cases: case 5 (Hi > Di): STALL before status
- // TU_LOG(MSC_DEBUG, " SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len);
+ // TU_LOG_DRV(" SCSI case 5 (Hi > Di): %lu > %lu\r\n", p_cbw->total_bytes, p_msc->xferred_len);
usbd_edpt_stall(rhport, p_msc->ep_in);
} else {
TU_ASSERT(send_csw(p_msc));
@@ -434,7 +434,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
memcpy(p_cbw, _mscd_epbuf.buf, sizeof(msc_cbw_t));
TU_LOG_DRV(" SCSI Command [Lun%u]: %s\r\n", p_cbw->lun, tu_lookup_find(&_msc_scsi_cmd_table, p_cbw->command[0]));
- //TU_LOG_MEM(MSC_DEBUG, p_cbw, xferred_bytes, 2);
+ // TU_LOG_MEM(CFG_TUD_MSC_LOG_LEVEL, p_cbw, xferred_bytes, 2);
p_csw->signature = MSC_CSW_SIGNATURE;
p_csw->tag = p_cbw->tag;
@@ -491,7 +491,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
} else if (resplen == 0) {
if (p_cbw->total_bytes) {
// 6.7 The 13 Cases: case 4 (Hi > Dn)
- // TU_LOG(MSC_DEBUG, " SCSI case 4 (Hi > Dn): %lu\r\n", p_cbw->total_bytes);
+ // TU_LOG_DRV(" SCSI case 4 (Hi > Dn): %lu\r\n", p_cbw->total_bytes);
fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED);
} else {
// case 1 Hn = Dn: all good
@@ -500,7 +500,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
} else {
if (p_cbw->total_bytes == 0) {
// 6.7 The 13 Cases: case 2 (Hn < Di)
- // TU_LOG(MSC_DEBUG, " SCSI case 2 (Hn < Di): %lu\r\n", p_cbw->total_bytes);
+ // TU_LOG_DRV(" SCSI case 2 (Hn < Di): %lu\r\n", p_cbw->total_bytes);
fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED);
} else {
// cannot return more than host expect
@@ -515,7 +515,8 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
case MSC_STAGE_DATA:
TU_LOG_DRV(" SCSI Data [Lun%u]\r\n", p_cbw->lun);
- //TU_LOG_MEM(MSC_DEBUG, _mscd_epbuf.buf, xferred_bytes, 2);
+ TU_ASSERT(xferred_bytes <= CFG_TUD_MSC_EP_BUFSIZE); // sanity check to avoid buffer overflow
+ // TU_LOG_MEM(CFG_TUD_MSC_LOG_LEVEL, _mscd_epbuf.buf, xferred_bytes, 2);
if (SCSI_CMD_READ_10 == p_cbw->command[0]) {
p_msc->xferred_len += xferred_bytes;
@@ -562,7 +563,7 @@ bool mscd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t
// Wait for the Status phase to complete
if ((ep_addr == p_msc->ep_in) && (xferred_bytes == sizeof(msc_csw_t))) {
TU_LOG_DRV(" SCSI Status [Lun%u] = %u\r\n", p_cbw->lun, p_csw->status);
- // TU_LOG_MEM(MSC_DEBUG, p_csw, xferred_bytes, 2);
+ // TU_LOG_MEM(CFG_TUD_MSC_LOG_LEVEL, p_csw, xferred_bytes, 2);
// Invoke complete callback if defined
// Note: There is racing issue with samd51 + qspi flash testing with arduino
@@ -897,21 +898,19 @@ static void proc_write10_next(mscd_interface_t* p_msc, uint32_t xferred_bytes, i
// update actual byte before failed
p_msc->xferred_len += xferred_bytes;
- // Set sense
msc_cbw_t const* p_cbw = &p_msc->cbw;
set_sense_medium_not_present(p_cbw->lun);
-
fail_scsi_op(p_msc, MSC_CSW_STATUS_FAILED);
} else {
- // Application consume less than what we got (including zero)
if ((uint32_t)nbytes < xferred_bytes) {
- uint32_t const left_over = xferred_bytes - (uint32_t)nbytes;
+ // Application consume less than what we got (including zero)
+ const uint32_t left_over = xferred_bytes - (uint32_t)nbytes;
if (nbytes > 0) {
p_msc->xferred_len += (uint16_t)nbytes;
memmove(_mscd_epbuf.buf, _mscd_epbuf.buf + nbytes, left_over);
}
- // simulate an transfer complete with adjusted parameters --> callback will be invoked with adjusted parameter
+ // simulate a transfer complete with adjusted parameters --> callback will be invoked with adjusted parameter
uint8_t rhport = p_msc->rhport;
dcd_event_xfer_complete(rhport, p_msc->ep_out, left_over, XFER_RESULT_SUCCESS, false);
} else {
diff --git a/src/class/vendor/vendor_device.c b/src/class/vendor/vendor_device.c
index 6f9b4853f..2fc0ac944 100644
--- a/src/class/vendor/vendor_device.c
+++ b/src/class/vendor/vendor_device.c
@@ -197,7 +197,7 @@ void vendord_reset(uint8_t rhport) {
uint16_t vendord_open(uint8_t rhport, const tusb_desc_interface_t* desc_itf, uint16_t max_len) {
TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass, 0);
const uint8_t* p_desc = tu_desc_next(desc_itf);
- const uint8_t* desc_end = p_desc + max_len;
+ const uint8_t* desc_end = (uint8_t const*)desc_itf + max_len;
// Find available interface
vendord_interface_t* p_vendor = NULL;
diff --git a/src/common/tusb_common.h b/src/common/tusb_common.h
index 74cac965d..0351a3d8f 100644
--- a/src/common/tusb_common.h
+++ b/src/common/tusb_common.h
@@ -120,6 +120,22 @@ TU_ATTR_ALWAYS_INLINE static inline int tu_memcpy_s(void *dest, size_t destsz, c
return 0;
}
+TU_ATTR_ALWAYS_INLINE static inline bool tu_mem_is_zero(const void *buffer, size_t size) {
+ const uint8_t* buf8 = (const uint8_t*) buffer;
+ for (size_t i = 0; i < size; i++) {
+ if (buf8[i] != 0) { return false; }
+ }
+ return true;
+}
+
+TU_ATTR_ALWAYS_INLINE static inline bool tu_mem_is_ff(const void *buffer, size_t size) {
+ const uint8_t* buf8 = (const uint8_t*) buffer;
+ for (size_t i = 0; i < size; i++) {
+ if (buf8[i] != 0xff) { return false; }
+ }
+ return true;
+}
+
//------------- Bytes -------------//
TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_u32(uint8_t b3, uint8_t b2, uint8_t b1, uint8_t b0) {
@@ -181,8 +197,7 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_round_up(uint32_t v, uint32_t f)
// log2 of a value is its MSB's position
// TODO use clz TODO remove
-static inline uint8_t tu_log2(uint32_t value)
-{
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_log2(uint32_t value) {
uint8_t result = 0;
while (value >>= 1) { result++; }
return result;
@@ -193,8 +208,7 @@ static inline uint8_t tu_log2(uint32_t value)
// return sizeof(uint32_t) * CHAR_BIT - __builtin_clz(x) - 1;
//}
-static inline bool tu_is_power_of_two(uint32_t value)
-{
+TU_ATTR_ALWAYS_INLINE static inline bool tu_is_power_of_two(uint32_t value) {
return (value != 0) && ((value & (value - 1)) == 0);
}
@@ -205,27 +219,23 @@ static inline bool tu_is_power_of_two(uint32_t value)
typedef struct { uint16_t val; } TU_ATTR_PACKED tu_unaligned_uint16_t;
typedef struct { uint32_t val; } TU_ATTR_PACKED tu_unaligned_uint32_t;
-TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void* mem)
-{
- tu_unaligned_uint32_t const* ua32 = (tu_unaligned_uint32_t const*) mem;
+TU_ATTR_ALWAYS_INLINE static inline uint32_t tu_unaligned_read32(const void *mem) {
+ tu_unaligned_uint32_t const *ua32 = (tu_unaligned_uint32_t const *) mem;
return ua32->val;
}
-TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void* mem, uint32_t value)
-{
- tu_unaligned_uint32_t* ua32 = (tu_unaligned_uint32_t*) mem;
+TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write32(void *mem, uint32_t value) {
+ tu_unaligned_uint32_t *ua32 = (tu_unaligned_uint32_t *) mem;
ua32->val = value;
}
-TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void* mem)
-{
- tu_unaligned_uint16_t const* ua16 = (tu_unaligned_uint16_t const*) mem;
+TU_ATTR_ALWAYS_INLINE static inline uint16_t tu_unaligned_read16(const void *mem) {
+ tu_unaligned_uint16_t const *ua16 = (tu_unaligned_uint16_t const *) mem;
return ua16->val;
}
-TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void* mem, uint16_t value)
-{
- tu_unaligned_uint16_t* ua16 = (tu_unaligned_uint16_t*) mem;
+TU_ATTR_ALWAYS_INLINE static inline void tu_unaligned_write16(void *mem, uint16_t value) {
+ tu_unaligned_uint16_t *ua16 = (tu_unaligned_uint16_t *) mem;
ua16->val = value;
}
diff --git a/src/common/tusb_fifo.c b/src/common/tusb_fifo.c
index 5f2dcabad..ecf002b09 100644
--- a/src/common/tusb_fifo.c
+++ b/src/common/tusb_fifo.c
@@ -916,8 +916,11 @@ bool tu_fifo_clear(tu_fifo_t *f)
Overwritable mode the fifo is set to
*/
/******************************************************************************/
-bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable)
-{
+bool tu_fifo_set_overwritable(tu_fifo_t *f, bool overwritable) {
+ if (f->overwritable == overwritable) {
+ return true;
+ }
+
_ff_lock(f->mutex_wr);
_ff_lock(f->mutex_rd);
diff --git a/src/common/tusb_private.h b/src/common/tusb_private.h
index c71775abb..31aca8a31 100644
--- a/src/common/tusb_private.h
+++ b/src/common/tusb_private.h
@@ -67,7 +67,7 @@ typedef struct {
//--------------------------------------------------------------------+
// Check if endpoint descriptor is valid per USB specs
-bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed);
+bool tu_edpt_validate(tusb_desc_endpoint_t const * desc_ep, tusb_speed_t speed, bool is_host);
// Bind all endpoint of a interface descriptor to class driver
void tu_edpt_bind_driver(uint8_t ep2drv[][2], tusb_desc_interface_t const* p_desc, uint16_t desc_len, uint8_t driver_id);
@@ -138,7 +138,7 @@ uint32_t tu_edpt_stream_read(uint8_t hwid, tu_edpt_stream_t* s, void* buffer, ui
// Start an usb transfer if endpoint is not busy
uint32_t tu_edpt_stream_read_xfer(uint8_t hwid, tu_edpt_stream_t* s);
-// Must be called in the transfer complete callback
+// Complete read transfer by writing EP -> FIFO. Must be called in the transfer complete callback
TU_ATTR_ALWAYS_INLINE static inline
void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_bytes) {
if (tu_fifo_depth(&s->ff)) {
@@ -146,11 +146,11 @@ void tu_edpt_stream_read_xfer_complete(tu_edpt_stream_t* s, uint32_t xferred_byt
}
}
-// Same as tu_edpt_stream_read_xfer_complete but skip the first n bytes
+// Complete read transfer with provided buffer
TU_ATTR_ALWAYS_INLINE static inline
-void tu_edpt_stream_read_xfer_complete_offset(tu_edpt_stream_t* s, uint32_t xferred_bytes, uint32_t skip_offset) {
- if (tu_fifo_depth(&s->ff) && (skip_offset < xferred_bytes)) {
- tu_fifo_write_n(&s->ff, s->ep_buf + skip_offset, (uint16_t) (xferred_bytes - skip_offset));
+void tu_edpt_stream_read_xfer_complete_with_buf(tu_edpt_stream_t* s, const void * buf, uint32_t xferred_bytes) {
+ if (tu_fifo_depth(&s->ff)) {
+ tu_fifo_write_n(&s->ff, buf, (uint16_t) xferred_bytes);
}
}
diff --git a/src/common/tusb_types.h b/src/common/tusb_types.h
index 9e4d9380c..e000a4bd3 100644
--- a/src/common/tusb_types.h
+++ b/src/common/tusb_types.h
@@ -281,7 +281,8 @@ typedef enum {
// TODO remove
enum {
DESC_OFFSET_LEN = 0,
- DESC_OFFSET_TYPE = 1
+ DESC_OFFSET_TYPE = 1,
+ DESC_OFFSET_SUBTYPE = 2
};
enum {
@@ -302,9 +303,9 @@ typedef enum {
enum {
CONTROL_STAGE_IDLE = 0,
- CONTROL_STAGE_SETUP,
- CONTROL_STAGE_DATA,
- CONTROL_STAGE_ACK
+ CONTROL_STAGE_SETUP, // 1
+ CONTROL_STAGE_DATA, // 2
+ CONTROL_STAGE_ACK // 3
};
enum {
@@ -462,7 +463,7 @@ TU_VERIFY_STATIC( sizeof(tusb_desc_interface_assoc_t) == 8, "size is not correct
typedef struct TU_ATTR_PACKED {
uint8_t bLength ; ///< Size of this descriptor in bytes
uint8_t bDescriptorType ; ///< Descriptor Type
- uint16_t unicode_string[];
+ uint16_t utf16le[];
} tusb_desc_string_t;
// USB Binary Device Object Store (BOS)
@@ -570,14 +571,19 @@ TU_ATTR_ALWAYS_INLINE static inline uint8_t const * tu_desc_next(void const* des
return desc8 + desc8[DESC_OFFSET_LEN];
}
+// get descriptor length
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) {
+ return ((uint8_t const*) desc)[DESC_OFFSET_LEN];
+}
+
// get descriptor type
TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_type(void const* desc) {
return ((uint8_t const*) desc)[DESC_OFFSET_TYPE];
}
-// get descriptor length
-TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_len(void const* desc) {
- return ((uint8_t const*) desc)[DESC_OFFSET_LEN];
+// get descriptor subtype
+TU_ATTR_ALWAYS_INLINE static inline uint8_t tu_desc_subtype(void const* desc) {
+ return ((uint8_t const*) desc)[DESC_OFFSET_SUBTYPE];
}
// find descriptor that match byte1 (type)
diff --git a/src/device/usbd.c b/src/device/usbd.c
index 8435b5c02..cd7e2de89 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -578,8 +578,7 @@ static void usbd_reset(uint8_t rhport) {
}
bool tud_task_event_ready(void) {
- // Skip if stack is not initialized
- if (!tud_inited()) return false;
+ TU_VERIFY(tud_inited()); // Skip if stack is not initialized
return !osal_queue_empty(_usbd_q);
}
@@ -701,7 +700,9 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) {
case USBD_EVENT_FUNC_CALL:
TU_LOG_USBD("\r\n");
- if (event.func_call.func) event.func_call.func(event.func_call.param);
+ if (event.func_call.func) {
+ event.func_call.func(event.func_call.param);
+ }
break;
case DCD_EVENT_SOF:
@@ -718,7 +719,7 @@ void tud_task_ext(uint32_t timeout_ms, bool in_isr) {
#if CFG_TUSB_OS != OPT_OS_NONE && CFG_TUSB_OS != OPT_OS_PICO
// return if there is no more events, for application to run other background
- if (osal_queue_empty(_usbd_q)) return;
+ if (osal_queue_empty(_usbd_q)) { return; }
#endif
}
}
@@ -1049,7 +1050,14 @@ static bool process_set_config(uint8_t rhport, uint8_t cfg_num)
#endif
#if CFG_TUD_MIDI
- if ( driver->open == midid_open ) assoc_itf_count = 2;
+ if (driver->open == midid_open) {
+ // If there is a class-compliant Audio Control Class, then 2 interfaces. Otherwise, only one
+ if (TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass &&
+ AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass &&
+ AUDIO_FUNC_PROTOCOL_CODE_UNDEF == desc_itf->bInterfaceProtocol) {
+ assoc_itf_count = 2;
+ }
+ }
#endif
#if CFG_TUD_BTH && CFG_TUD_BTH_ISO_ALT_COUNT
@@ -1306,7 +1314,7 @@ bool usbd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep) {
rhport = _usbd_rhport;
TU_ASSERT(tu_edpt_number(desc_ep->bEndpointAddress) < CFG_TUD_ENDPPOINT_MAX);
- TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed));
+ TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed, false));
return dcd_edpt_open(rhport, desc_ep);
}
@@ -1507,7 +1515,7 @@ bool usbd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const* desc_ep)
uint8_t const dir = tu_edpt_dir(desc_ep->bEndpointAddress);
TU_ASSERT(epnum < CFG_TUD_ENDPPOINT_MAX);
- TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed));
+ TU_ASSERT(tu_edpt_validate(desc_ep, (tusb_speed_t) _usbd_dev.speed, false));
_usbd_dev.ep_status[epnum][dir].stalled = 0;
_usbd_dev.ep_status[epnum][dir].busy = 0;
diff --git a/src/host/hcd.h b/src/host/hcd.h
index 56b6fdb5d..b20d96d54 100644
--- a/src/host/hcd.h
+++ b/src/host/hcd.h
@@ -163,8 +163,12 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr);
//--------------------------------------------------------------------+
// Open an endpoint
+// return true if successfully opened or endpoint is currently opened
bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * ep_desc);
+// Close an endpoint
+bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr);
+
// Submit a transfer, when complete hcd_event_xfer_complete() must be invoked
bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen);
diff --git a/src/host/hub.c b/src/host/hub.c
index e97014443..61efa8ba5 100644
--- a/src/host/hub.c
+++ b/src/host/hub.c
@@ -40,29 +40,36 @@
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
-typedef struct
-{
+typedef struct {
uint8_t itf_num;
uint8_t ep_in;
- uint8_t port_count;
- CFG_TUH_MEM_ALIGN uint8_t status_change;
- CFG_TUH_MEM_ALIGN hub_port_status_response_t port_status;
- CFG_TUH_MEM_ALIGN hub_status_response_t hub_status;
+ // from hub descriptor
+ uint8_t bNbrPorts;
+ uint8_t bPwrOn2PwrGood_2ms; // port power on to good, in 2ms unit
+ // uint16_t wHubCharacteristics;
+
+ hub_port_status_response_t port_status;
} hub_interface_t;
-CFG_TUH_MEM_SECTION static hub_interface_t hub_data[CFG_TUH_HUB];
-CFG_TUH_MEM_SECTION CFG_TUH_MEM_ALIGN static uint8_t _hub_buffer[sizeof(descriptor_hub_desc_t)];
+typedef struct {
+ TUH_EPBUF_DEF(status_change, 4); // interrupt endpoint
+ TUH_EPBUF_DEF(ctrl_buf, CFG_TUH_HUB_BUFSIZE);
+} hub_epbuf_t;
-TU_ATTR_ALWAYS_INLINE
-static inline hub_interface_t* get_itf(uint8_t dev_addr)
-{
- return &hub_data[dev_addr-1-CFG_TUH_DEVICE_MAX];
+static hub_interface_t hub_itfs[CFG_TUH_HUB];
+CFG_TUH_MEM_SECTION static hub_epbuf_t hub_epbufs[CFG_TUH_HUB];
+
+TU_ATTR_ALWAYS_INLINE static inline hub_interface_t* get_hub_itf(uint8_t daddr) {
+ return &hub_itfs[daddr-1-CFG_TUH_DEVICE_MAX];
}
-#if CFG_TUSB_DEBUG >= 2
-static char const* const _hub_feature_str[] =
-{
+TU_ATTR_ALWAYS_INLINE static inline hub_epbuf_t* get_hub_epbuf(uint8_t daddr) {
+ return &hub_epbufs[daddr-1-CFG_TUH_DEVICE_MAX];
+}
+
+#if CFG_TUSB_DEBUG >= HUB_DEBUG
+static char const* const _hub_feature_str[] = {
[HUB_FEATURE_PORT_CONNECTION ] = "PORT_CONNECTION",
[HUB_FEATURE_PORT_ENABLE ] = "PORT_ENABLE",
[HUB_FEATURE_PORT_SUSPEND ] = "PORT_SUSPEND",
@@ -84,12 +91,9 @@ static char const* const _hub_feature_str[] =
// HUB
//--------------------------------------------------------------------+
bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
- tusb_control_request_t const request =
- {
- .bmRequestType_bit =
- {
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ tusb_control_request_t const request = {
+ .bmRequestType_bit = {
.recipient = (hub_port == 0) ? TUSB_REQ_RCPT_DEVICE : TUSB_REQ_RCPT_OTHER,
.type = TUSB_REQ_TYPE_CLASS,
.direction = TUSB_DIR_OUT
@@ -100,8 +104,7 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
.wLength = 0
};
- tuh_xfer_t xfer =
- {
+ tuh_xfer_t xfer = {
.daddr = hub_addr,
.ep_addr = 0,
.setup = &request,
@@ -110,18 +113,15 @@ bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
.user_data = user_data
};
- TU_LOG2("HUB Clear Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port);
- TU_ASSERT( tuh_control_xfer(&xfer) );
+ TU_LOG_DRV("HUB Clear Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port);
+ TU_ASSERT(tuh_control_xfer(&xfer));
return true;
}
bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
- tusb_control_request_t const request =
- {
- .bmRequestType_bit =
- {
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ tusb_control_request_t const request = {
+ .bmRequestType_bit = {
.recipient = (hub_port == 0) ? TUSB_REQ_RCPT_DEVICE : TUSB_REQ_RCPT_OTHER,
.type = TUSB_REQ_TYPE_CLASS,
.direction = TUSB_DIR_OUT
@@ -132,8 +132,7 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
.wLength = 0
};
- tuh_xfer_t xfer =
- {
+ tuh_xfer_t xfer = {
.daddr = hub_addr,
.ep_addr = 0,
.setup = &request,
@@ -142,18 +141,15 @@ bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
.user_data = user_data
};
- TU_LOG2("HUB Set Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port);
+ TU_LOG_DRV("HUB Set Feature: %s, addr = %u port = %u\r\n", _hub_feature_str[feature], hub_addr, hub_port);
TU_ASSERT( tuh_control_xfer(&xfer) );
return true;
}
bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data)
-{
- tusb_control_request_t const request =
- {
- .bmRequestType_bit =
- {
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ tusb_control_request_t const request = {
+ .bmRequestType_bit = {
.recipient = (hub_port == 0) ? TUSB_REQ_RCPT_DEVICE : TUSB_REQ_RCPT_OTHER,
.type = TUSB_REQ_TYPE_CLASS,
.direction = TUSB_DIR_IN
@@ -161,11 +157,10 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp,
.bRequest = HUB_REQUEST_GET_STATUS,
.wValue = 0,
.wIndex = hub_port,
- .wLength = 4
+ .wLength = tu_htole16(4)
};
- tuh_xfer_t xfer =
- {
+ tuh_xfer_t xfer = {
.daddr = hub_addr,
.ep_addr = 0,
.setup = &request,
@@ -174,7 +169,7 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp,
.user_data = user_data
};
- TU_LOG2("HUB Get Port Status: addr = %u port = %u\r\n", hub_addr, hub_port);
+ TU_LOG_DRV("HUB Get Port Status: addr = %u port = %u\r\n", hub_addr, hub_port);
TU_VERIFY( tuh_control_xfer(&xfer) );
return true;
}
@@ -183,7 +178,7 @@ bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void* resp,
// CLASS-USBH API (don't require to verify parameters)
//--------------------------------------------------------------------+
bool hub_init(void) {
- tu_memclr(hub_data, sizeof(hub_data));
+ tu_memclr(hub_itfs, sizeof(hub_itfs));
return true;
}
@@ -191,40 +186,32 @@ bool hub_deinit(void) {
return true;
}
-bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len)
-{
+bool hub_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len) {
(void) rhport;
TU_VERIFY(TUSB_CLASS_HUB == itf_desc->bInterfaceClass &&
0 == itf_desc->bInterfaceSubClass);
+ TU_VERIFY(itf_desc->bInterfaceProtocol <= 1); // not support multiple TT yet
- // hub driver does not support multiple TT yet
- TU_VERIFY(itf_desc->bInterfaceProtocol <= 1);
-
- // msc driver length is fixed
uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(tusb_desc_endpoint_t);
TU_ASSERT(drv_len <= max_len);
- //------------- Interrupt Status endpoint -------------//
+ // Interrupt Status endpoint
tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *) tu_desc_next(itf_desc);
-
TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType &&
TUSB_XFER_INTERRUPT == desc_ep->bmAttributes.xfer, 0);
-
TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep));
- hub_interface_t* p_hub = get_itf(dev_addr);
-
+ hub_interface_t* p_hub = get_hub_itf(dev_addr);
p_hub->itf_num = itf_desc->bInterfaceNumber;
p_hub->ep_in = desc_ep->bEndpointAddress;
return true;
}
-void hub_close(uint8_t dev_addr)
-{
+void hub_close(uint8_t dev_addr) {
TU_VERIFY(dev_addr > CFG_TUH_DEVICE_MAX, );
- hub_interface_t* p_hub = get_itf(dev_addr);
+ hub_interface_t* p_hub = get_hub_itf(dev_addr);
if (p_hub->ep_in) {
TU_LOG_DRV(" HUB close addr = %d\r\n", dev_addr);
@@ -232,30 +219,33 @@ void hub_close(uint8_t dev_addr)
}
}
-bool hub_edpt_status_xfer(uint8_t dev_addr)
-{
- hub_interface_t* hub_itf = get_itf(dev_addr);
- return usbh_edpt_xfer(dev_addr, hub_itf->ep_in, &hub_itf->status_change, 1);
-}
+bool hub_edpt_status_xfer(uint8_t daddr) {
+ hub_interface_t* p_hub = get_hub_itf(daddr);
+ hub_epbuf_t* p_epbuf = get_hub_epbuf(daddr);
+ TU_VERIFY(usbh_edpt_claim(daddr, p_hub->ep_in));
+ if (!usbh_edpt_xfer(daddr, p_hub->ep_in, p_epbuf->status_change, 1)) {
+ usbh_edpt_release(daddr, p_hub->ep_in);
+ return false;
+ }
+
+ return true;
+}
//--------------------------------------------------------------------+
// Set Configure
//--------------------------------------------------------------------+
-
static void config_set_port_power (tuh_xfer_t* xfer);
static void config_port_power_complete (tuh_xfer_t* xfer);
-bool hub_set_config(uint8_t dev_addr, uint8_t itf_num)
-{
- hub_interface_t* p_hub = get_itf(dev_addr);
+bool hub_set_config(uint8_t dev_addr, uint8_t itf_num) {
+ hub_interface_t* p_hub = get_hub_itf(dev_addr);
TU_ASSERT(itf_num == p_hub->itf_num);
+ hub_epbuf_t* p_epbuf = get_hub_epbuf(dev_addr);
// Get Hub Descriptor
- tusb_control_request_t const request =
- {
- .bmRequestType_bit =
- {
+ tusb_control_request_t const request = {
+ .bmRequestType_bit = {
.recipient = TUSB_REQ_RCPT_DEVICE,
.type = TUSB_REQ_TYPE_CLASS,
.direction = TUSB_DIR_IN
@@ -263,34 +253,33 @@ bool hub_set_config(uint8_t dev_addr, uint8_t itf_num)
.bRequest = HUB_REQUEST_GET_DESCRIPTOR,
.wValue = 0,
.wIndex = 0,
- .wLength = sizeof(descriptor_hub_desc_t)
+ .wLength = sizeof(hub_desc_cs_t)
};
- tuh_xfer_t xfer =
- {
+ tuh_xfer_t xfer = {
.daddr = dev_addr,
.ep_addr = 0,
.setup = &request,
- .buffer = _hub_buffer,
+ .buffer = p_epbuf->ctrl_buf,
.complete_cb = config_set_port_power,
.user_data = 0
};
- TU_ASSERT( tuh_control_xfer(&xfer) );
-
+ TU_ASSERT(tuh_control_xfer(&xfer));
return true;
}
-static void config_set_port_power (tuh_xfer_t* xfer)
-{
+static void config_set_port_power (tuh_xfer_t* xfer) {
TU_ASSERT(XFER_RESULT_SUCCESS == xfer->result, );
uint8_t const daddr = xfer->daddr;
- hub_interface_t* p_hub = get_itf(daddr);
+ hub_interface_t* p_hub = get_hub_itf(daddr);
+ hub_epbuf_t* p_epbuf = get_hub_epbuf(daddr);
// only use number of ports in hub descriptor
- descriptor_hub_desc_t const* desc_hub = (descriptor_hub_desc_t const*) _hub_buffer;
- p_hub->port_count = desc_hub->bNbrPorts;
+ hub_desc_cs_t const* desc_hub = (hub_desc_cs_t const*) p_epbuf->ctrl_buf;
+ p_hub->bNbrPorts = desc_hub->bNbrPorts;
+ p_hub->bPwrOn2PwrGood_2ms = desc_hub->bPwrOn2PwrGood;
// May need to GET_STATUS
@@ -299,22 +288,21 @@ static void config_set_port_power (tuh_xfer_t* xfer)
hub_port_set_feature(daddr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0);
}
-static void config_port_power_complete (tuh_xfer_t* xfer)
-{
+static void config_port_power_complete (tuh_xfer_t* xfer) {
TU_ASSERT(XFER_RESULT_SUCCESS == xfer->result, );
uint8_t const daddr = xfer->daddr;
- hub_interface_t* p_hub = get_itf(daddr);
+ hub_interface_t* p_hub = get_hub_itf(daddr);
- if (xfer->setup->wIndex == p_hub->port_count)
- {
+ if (xfer->setup->wIndex == p_hub->bNbrPorts) {
// All ports are power -> queue notification status endpoint and
// complete the SET CONFIGURATION
- TU_ASSERT( usbh_edpt_xfer(daddr, p_hub->ep_in, &p_hub->status_change, 1), );
-
+ if (!hub_edpt_status_xfer(daddr)) {
+ TU_MESS_FAILED();
+ TU_BREAKPOINT();
+ }
usbh_driver_set_config_complete(daddr, p_hub->itf_num);
- }else
- {
+ } else {
// power next port
uint8_t const hub_port = (uint8_t) (xfer->setup->wIndex + 1);
hub_port_set_feature(daddr, hub_port, HUB_FEATURE_PORT_POWER, config_port_power_complete, 0);
@@ -324,180 +312,162 @@ static void config_port_power_complete (tuh_xfer_t* xfer)
//--------------------------------------------------------------------+
// Connection Changes
//--------------------------------------------------------------------+
-
-static void hub_port_get_status_complete (tuh_xfer_t* xfer);
-static void hub_get_status_complete (tuh_xfer_t* xfer);
+static void get_status_complete (tuh_xfer_t* xfer);
+static void port_get_status_complete (tuh_xfer_t* xfer);
+static void port_clear_feature_complete_stub(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);
// callback as response of interrupt endpoint polling
-bool hub_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
- (void) xferred_bytes; // TODO can be more than 1 for hub with lots of ports
+bool hub_xfer_cb(uint8_t daddr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
+ (void) xferred_bytes;
(void) ep_addr;
- TU_VERIFY(result == XFER_RESULT_SUCCESS);
- hub_interface_t* p_hub = get_itf(dev_addr);
+ bool processed = false; // true if new status is processed
- uint8_t const status_change = p_hub->status_change;
- TU_LOG2(" Hub Status Change = 0x%02X\r\n", status_change);
+ if (result == XFER_RESULT_SUCCESS) {
+ hub_interface_t* p_hub = get_hub_itf(daddr);
+ hub_epbuf_t *p_epbuf = get_hub_epbuf(daddr);
+ const uint8_t status_change = p_epbuf->status_change[0];
+ TU_LOG_DRV(" Hub Status Change = 0x%02X\r\n", status_change);
- if ( status_change == 0 ) {
- // The status change event was neither for the hub, nor for any of its ports.
- // This shouldn't happen, but it does with some devices.
- // Initiate the next interrupt poll here.
- return hub_edpt_status_xfer(dev_addr);
- }
-
- if (tu_bit_test(status_change, 0)) {
- // Hub bit 0 is for the hub device events
- if (hub_port_get_status(dev_addr, 0, &p_hub->hub_status, hub_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(status_change, port) ) {
- 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);
+ if (status_change == 0) {
+ // The status change event was neither for the hub, nor for any of its ports.
+ // This shouldn't happen, but it does with some devices. Re-Initiate the interrupt poll.
+ processed = false;
+ } else if (tu_bit_test(status_change, 0)) {
+ // Hub bit 0 is for the hub device events
+ processed = hub_get_status(daddr, p_epbuf->ctrl_buf, get_status_complete, 0);
+ } else {
+ // Hub bits 1 to n are hub port events
+ for (uint8_t port=1; port <= p_hub->bNbrPorts; port++) {
+ if (tu_bit_test(status_change, port)) {
+ processed = hub_port_get_status(daddr, port, p_epbuf->ctrl_buf, port_get_status_complete, 0);
+ break; // after completely processed one port, we will re-queue the status poll and handle next one
}
- break;
}
}
}
- // NOTE: next status transfer is queued by usbh.c after handling this request
+ // If new status event is processed: next status pool is queued by usbh.c after handled this request
+ // Otherwise re-queue the status poll here
+ if (!processed) {
+ TU_ASSERT(hub_edpt_status_xfer(daddr));
+ }
+
return true;
}
-static void hub_clear_feature_complete_stub(tuh_xfer_t* xfer)
-{
- TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
+static void port_clear_feature_complete_stub(tuh_xfer_t* xfer) {
hub_edpt_status_xfer(xfer->daddr);
}
-static void hub_get_status_complete (tuh_xfer_t* xfer)
-{
- TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
+static void get_status_complete(tuh_xfer_t *xfer) {
+ const uint8_t daddr = xfer->daddr;
- 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 , );
+ bool processed = false; // true if new status is processed
+ if (xfer->result == XFER_RESULT_SUCCESS) {
+ hub_status_response_t hub_status = *((const hub_status_response_t *) (uintptr_t) xfer->buffer);
- TU_LOG2("HUB Got hub status, addr = %u, status = %04x\r\n", daddr, p_hub->hub_status.change.value);
+ TU_LOG_DRV("HUB Got hub status, addr = %u, status = %04x\r\n", daddr, 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);
+ if (hub_status.change.local_power_source) {
+ TU_LOG_DRV(" Local Power Change\r\n");
+ processed = hub_clear_feature(daddr, HUB_FEATURE_HUB_LOCAL_POWER_CHANGE, port_clear_feature_complete_stub, 0);
+ } else if (hub_status.change.over_current) {
+ TU_LOG_DRV(" Over Current\r\n");
+ processed = hub_clear_feature(daddr, HUB_FEATURE_HUB_OVER_CURRENT_CHANGE, port_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);
+
+ if (!processed) {
+ TU_ASSERT(hub_edpt_status_xfer(daddr), );
}
}
-static void hub_port_get_status_complete (tuh_xfer_t* xfer)
-{
- TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
+static void port_get_status_complete(tuh_xfer_t *xfer) {
+ const uint8_t daddr = xfer->daddr;
+ bool processed = false; // true if new status is processed
- 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);
+ if (xfer->result == XFER_RESULT_SUCCESS) {
+ const uint8_t port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
+ hub_interface_t *p_hub = get_hub_itf(daddr);
+ p_hub->port_status = *((const hub_port_status_response_t *) (uintptr_t) xfer->buffer);
- // Connection change
- if (p_hub->port_status.change.connection)
- {
- // Port is powered and enabled
- //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, );
+ // Clear port status change interrupts
+ if (p_hub->port_status.change.connection) {
+ // Connection change
+ // Port is powered and enabled
+ //TU_VERIFY(port_status.status_current.port_power && port_status.status_current.port_enable, );
- // Acknowledge Port Connection Change
- hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete, 0);
- }else
- {
- // 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);
+ // Acknowledge Port Connection Change
+ processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_CONNECTION_CHANGE, connection_clear_conn_change_complete, 0);
+ } else if (p_hub->port_status.change.port_enable) {
+ processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_ENABLE_CHANGE, port_clear_feature_complete_stub, 0);
+ } else if (p_hub->port_status.change.suspend) {
+ processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_SUSPEND_CHANGE, port_clear_feature_complete_stub, 0);
+ } else if (p_hub->port_status.change.over_current) {
+ processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_OVER_CURRENT_CHANGE, port_clear_feature_complete_stub, 0);
+ } else if (p_hub->port_status.change.reset) {
+ processed = hub_port_clear_feature(daddr, port_num, HUB_FEATURE_PORT_RESET_CHANGE, port_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
+ }
- else
- {
- // prepare for next hub status
- // TODO continue with status_change, or maybe we can do it again with status
- hub_edpt_status_xfer(daddr);
- }
+ if (!processed) {
+ TU_ASSERT(hub_edpt_status_xfer(daddr), );
}
}
-static void connection_clear_conn_change_complete (tuh_xfer_t* xfer)
-{
- TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
+static void connection_clear_conn_change_complete (tuh_xfer_t* xfer) {
+ const uint8_t daddr = xfer->daddr;
- 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);
+ if (xfer->result != XFER_RESULT_SUCCESS) {
+ TU_ASSERT(hub_edpt_status_xfer(daddr), );
+ return;
+ }
- if ( p_hub->port_status.status.connection )
- {
+ hub_interface_t *p_hub = get_hub_itf(daddr);
+ const uint8_t port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
+
+ if (p_hub->port_status.status.connection) {
// Reset port if attach event
hub_port_reset(daddr, port_num, connection_port_reset_complete, 0);
- }else
- {
+ } else {
// submit detach event
- hcd_event_t event =
- {
+ const hcd_event_t event = {
.rhport = usbh_get_rhport(daddr),
.event_id = HCD_EVENT_DEVICE_REMOVE,
- .connection =
- {
+ .connection = {
.hub_addr = daddr,
.hub_port = port_num
}
};
-
hcd_event_handler(&event, false);
}
}
-static void connection_port_reset_complete (tuh_xfer_t* xfer)
-{
- TU_ASSERT(xfer->result == XFER_RESULT_SUCCESS, );
+static void connection_port_reset_complete (tuh_xfer_t* xfer) {
+ const uint8_t daddr = xfer->daddr;
- 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);
+ if (xfer->result != XFER_RESULT_SUCCESS) {
+ // retry port reset if failed
+ if (!tuh_control_xfer(xfer)) {
+ TU_ASSERT(hub_edpt_status_xfer(daddr), ); // back to status poll if failed to queue request
+ }
+ return;
+ }
+
+ const uint8_t port_num = (uint8_t) tu_le16toh(xfer->setup->wIndex);
// submit attach event
- hcd_event_t event =
- {
+ hcd_event_t event = {
.rhport = usbh_get_rhport(daddr),
.event_id = HCD_EVENT_DEVICE_ATTACH,
- .connection =
- {
+ .connection = {
.hub_addr = daddr,
.hub_port = port_num
}
};
-
hcd_event_handler(&event, false);
}
diff --git a/src/host/hub.h b/src/host/hub.h
index 385efe6b2..e4e576661 100644
--- a/src/host/hub.h
+++ b/src/host/hub.h
@@ -24,17 +24,8 @@
* This file is part of the TinyUSB stack.
*/
-/** \ingroup group_class
- * \defgroup ClassDriver_Hub Hub (Host only)
- * \details Like most PC's OS, Hub support is completely hidden from Application. In fact, application cannot determine whether
- * a device is mounted directly via roothub or via a hub's port. All Hub-related procedures are performed and managed
- * by tinyusb stack. Unless you are trying to develop the stack itself, there are nothing else can be used by Application.
- * \note Due to my laziness, only 1-level of Hub is supported. In other way, the stack cannot mount a hub via another hub.
- * @{
- */
-
-#ifndef _TUSB_HUB_H_
-#define _TUSB_HUB_H_
+#ifndef TUSB_HUB_H_
+#define TUSB_HUB_H_
#include "common/tusb_common.h"
@@ -42,63 +33,23 @@
extern "C" {
#endif
-//D1...D0: Logical Power Switching Mode
-//00: Ganged power switching (all ports’power at
-//once)
-//01: Individual port power switching
-//1X: Reserved. Used only on 1.0 compliant hubs
-//that implement no power switching
-//D2: Identifies a Compound Device
-//0: Hub is not part of a compound device.
-//1: Hub is part of a compound device.
-//D4...D3: Over-current Protection Mode
-//00: Global Over-current Protection. The hub
-//reports over-current as a summation of all
-//ports’current draw, without a breakdown of
-//individual port over-current status.
-//01: Individual Port Over-current Protection. The
-//hub reports over-current on a per-port basis.
-//Each port has an over-current status.
-//1X: No Over-current Protection. This option is
-//allowed only for bus-powered hubs that do not
-//implement over-current protection.
+//--------------------------------------------------------------------+
+// Configuration
+//--------------------------------------------------------------------+
+
+#ifndef CFG_TUH_HUB_BUFSIZE
+ #define CFG_TUH_HUB_BUFSIZE 12
+#endif
+
+//--------------------------------------------------------------------+
//
-//D6...D5: TT Think TIme
-//00: TT requires at most 8 FS bit times of inter
-//transaction gap on a full-/low-speed
-//downstream bus.
-//01: TT requires at most 16 FS bit times.
-//10: TT requires at most 24 FS bit times.
-//11: TT requires at most 32 FS bit times.
-//D7: Port Indicators Supported
-//0: Port Indicators are not supported on its
-//downstream facing ports and the
-//PORT_INDICATOR request has no effect.
-//1: Port Indicators are supported on its
-//downstream facing ports and the
-//PORT_INDICATOR request controls the
-//indicators. See Section 11.5.3.
-//D15...D8: Reserved
-
-typedef struct TU_ATTR_PACKED{
- uint8_t bLength ; ///< Size of descriptor
- uint8_t bDescriptorType ; ///< Other_speed_Configuration Type
- uint8_t bNbrPorts;
- uint16_t wHubCharacteristics;
- uint8_t bPwrOn2PwrGood;
- uint8_t bHubContrCurrent;
- uint8_t DeviceRemovable; // bitmap each bit for a port (from bit1)
- uint8_t PortPwrCtrlMask; // just for compatibility, should be 0xff
-} descriptor_hub_desc_t;
-
-TU_VERIFY_STATIC( sizeof(descriptor_hub_desc_t) == 9, "size is not correct");
-
+//--------------------------------------------------------------------+
enum {
HUB_REQUEST_GET_STATUS = 0 ,
HUB_REQUEST_CLEAR_FEATURE = 1 ,
-
+ // 2 is reserved
HUB_REQUEST_SET_FEATURE = 3 ,
-
+ // 4-5 are reserved
HUB_REQUEST_GET_DESCRIPTOR = 6 ,
HUB_REQUEST_SET_DESCRIPTOR = 7 ,
HUB_REQUEST_CLEAR_TT_BUFFER = 8 ,
@@ -118,10 +69,10 @@ enum{
HUB_FEATURE_PORT_SUSPEND = 2,
HUB_FEATURE_PORT_OVER_CURRENT = 3,
HUB_FEATURE_PORT_RESET = 4,
-
+ // 5-7 are reserved
HUB_FEATURE_PORT_POWER = 8,
HUB_FEATURE_PORT_LOW_SPEED = 9,
-
+ // 10-15 are reserved
HUB_FEATURE_PORT_CONNECTION_CHANGE = 16,
HUB_FEATURE_PORT_ENABLE_CHANGE = 17,
HUB_FEATURE_PORT_SUSPEND_CHANGE = 18,
@@ -131,6 +82,41 @@ enum{
HUB_FEATURE_PORT_INDICATOR = 22
};
+enum {
+ HUB_CHARS_POWER_GANGED_SWITCHING = 0,
+ HUB_CHARS_POWER_INDIVIDUAL_SWITCHING = 1,
+};
+
+enum {
+ HUB_CHARS_OVER_CURRENT_GLOBAL = 0,
+ HUB_CHARS_OVER_CURRENT_INDIVIDUAL = 1,
+};
+
+typedef struct TU_ATTR_PACKED{
+ uint8_t bLength ; ///< Size of descriptor
+ uint8_t bDescriptorType ; ///< Other_speed_Configuration Type
+ uint8_t bNbrPorts;
+ uint16_t wHubCharacteristics;
+ uint8_t bPwrOn2PwrGood;
+ uint8_t bHubContrCurrent;
+ uint8_t DeviceRemovable; // bitmap each bit for a port (from bit1)
+ uint8_t PortPwrCtrlMask; // just for compatibility, should be 0xff
+} hub_desc_cs_t;
+TU_VERIFY_STATIC(sizeof(hub_desc_cs_t) == 9, "size is not correct");
+TU_VERIFY_STATIC(CFG_TUH_HUB_BUFSIZE >= sizeof(hub_desc_cs_t), "buffer is not big enough");
+
+typedef struct TU_ATTR_PACKED {
+ struct TU_ATTR_PACKED {
+ uint8_t logical_power_switching_mode : 2; // [0..1] gannged or individual power switching
+ uint8_t compound_device : 1; // [2] hub is part of compound device
+ uint8_t over_current_protect_mode : 2; // [3..4] global or individual port over-current protection
+ uint8_t tt_think_time : 2; // [5..6] TT think time
+ uint8_t port_indicator_supported : 1; // [7] port indicator supported
+ };
+ uint8_t rsv1;
+} hub_characteristics_t;
+TU_VERIFY_STATIC(sizeof(hub_characteristics_t) == 2, "size is not correct");
+
// data in response of HUB_REQUEST_GET_STATUS, wIndex = 0 (hub)
typedef struct {
union{
@@ -143,48 +129,52 @@ typedef struct {
uint16_t value;
} status, change;
} hub_status_response_t;
-
TU_VERIFY_STATIC( sizeof(hub_status_response_t) == 4, "size is not correct");
// data in response of HUB_REQUEST_GET_STATUS, wIndex = Port num
typedef struct {
- union {
+ union TU_ATTR_PACKED {
struct TU_ATTR_PACKED {
- uint16_t connection : 1;
- uint16_t port_enable : 1;
- uint16_t suspend : 1;
- uint16_t over_current : 1;
- uint16_t reset : 1;
+ // Bit 0-4 are for change & status
+ uint16_t connection : 1; // [0] 0 = no device, 1 = device connected
+ uint16_t port_enable : 1; // [1] port is enabled
+ uint16_t suspend : 1; // [2]
+ uint16_t over_current : 1; // [3] over-current exists
+ uint16_t reset : 1; // [4] 0 = no reset, 1 = resetting
- uint16_t : 3;
- uint16_t port_power : 1;
- uint16_t low_speed : 1;
- uint16_t high_speed : 1;
- uint16_t port_test_mode : 1;
- uint16_t port_indicator_control : 1;
- uint16_t TU_RESERVED : 3;
+ // From Bit 5 are for status only
+ uint16_t rsv5_7 : 3; // [5..7] reserved
+ uint16_t port_power : 1; // [8] 0 = port is off, 1 = port is on
+ uint16_t low_speed : 1; // [9] low speed device attached
+ uint16_t high_speed : 1; // [10] high speed device attached
+ uint16_t port_test_mode : 1; // [11] port in test mode
+ uint16_t port_indicator_control : 1; // [12] 0: default color, 1: indicator is software controlled
+ uint16_t TU_RESERVED : 3; // [13..15] reserved
};
uint16_t value;
} status, change;
} hub_port_status_response_t;
-
TU_VERIFY_STATIC( sizeof(hub_port_status_response_t) == 4, "size is not correct");
-// Clear feature
-bool hub_port_clear_feature (uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+//--------------------------------------------------------------------+
+// HUB API
+//--------------------------------------------------------------------+
-// Set feature
-bool hub_port_set_feature (uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+// Clear port feature
+bool hub_port_clear_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+
+// Set port feature
+bool hub_port_set_feature(uint8_t hub_addr, uint8_t hub_port, uint8_t feature,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data);
// Get port status
-bool hub_port_get_status (uint8_t hub_addr, uint8_t hub_port, void* resp,
- tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+bool hub_port_get_status(uint8_t hub_addr, uint8_t hub_port, void *resp,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data);
// Get status from Interrupt endpoint
-bool hub_edpt_status_xfer(uint8_t dev_addr);
+bool hub_edpt_status_xfer(uint8_t daddr);
// Reset a port
TU_ATTR_ALWAYS_INLINE static inline
@@ -192,13 +182,23 @@ bool hub_port_reset(uint8_t hub_addr, uint8_t hub_port, tuh_xfer_cb_t complete_c
return hub_port_set_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET, complete_cb, user_data);
}
-// Clear Reset Change
+// Clear Port Reset Change
TU_ATTR_ALWAYS_INLINE static inline
bool hub_port_clear_reset_change(uint8_t hub_addr, uint8_t hub_port, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
return hub_port_clear_feature(hub_addr, hub_port, HUB_FEATURE_PORT_RESET_CHANGE, complete_cb, user_data);
}
+// Get Hub status
+TU_ATTR_ALWAYS_INLINE static inline
+bool hub_get_status(uint8_t hub_addr, void* resp, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ return hub_port_get_status(hub_addr, 0, resp, complete_cb, user_data);
+}
+// Clear Hub feature
+TU_ATTR_ALWAYS_INLINE static inline
+bool hub_clear_feature(uint8_t hub_addr, uint8_t feature, tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ return hub_port_clear_feature(hub_addr, 0, feature, complete_cb, user_data);
+}
//--------------------------------------------------------------------+
// Internal Class Driver API
//--------------------------------------------------------------------+
@@ -206,13 +206,11 @@ bool hub_init (void);
bool hub_deinit (void);
bool hub_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *itf_desc, uint16_t max_len);
bool hub_set_config (uint8_t dev_addr, uint8_t itf_num);
-bool hub_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
+bool hub_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes);
void hub_close (uint8_t dev_addr);
#ifdef __cplusplus
}
#endif
-#endif /* _TUSB_HUB_H_ */
-
-/** @} */
+#endif
diff --git a/src/host/usbh.c b/src/host/usbh.c
index f022d93f1..778015327 100644
--- a/src/host/usbh.c
+++ b/src/host/usbh.c
@@ -44,25 +44,33 @@
#define CFG_TUH_INTERFACE_MAX 8
#endif
+enum {
+ USBH_CONTROL_RETRY_MAX = 3,
+};
+
//--------------------------------------------------------------------+
// Weak stubs: invoked if no strong implementation is available
//--------------------------------------------------------------------+
TU_ATTR_WEAK bool hcd_deinit(uint8_t rhport) {
- (void) rhport;
- return false;
+ (void) rhport; return false;
}
TU_ATTR_WEAK bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) {
- (void) rhport;
- (void) cfg_id;
- (void) cfg_param;
+ (void) rhport; (void) cfg_id; (void) cfg_param;
return false;
}
+TU_ATTR_WEAK void tuh_enum_descriptor_device_cb(uint8_t daddr, const tusb_desc_device_t *desc_device) {
+ (void) daddr; (void) desc_device;
+}
+
+TU_ATTR_WEAK bool tuh_enum_descriptor_configuration_cb(uint8_t daddr, uint8_t cfg_index, const tusb_desc_configuration_t *desc_config) {
+ (void) daddr; (void) cfg_index; (void) desc_config;
+ return true;
+}
+
TU_ATTR_WEAK void tuh_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr) {
- (void) rhport;
- (void) eventid;
- (void) in_isr;
+ (void) rhport; (void) eventid; (void) in_isr;
}
TU_ATTR_WEAK bool hcd_dcache_clean(const void* addr, uint32_t data_size) {
@@ -122,6 +130,7 @@ typedef struct {
uint8_t i_manufacturer;
uint8_t i_product;
uint8_t i_serial;
+ uint8_t bNumConfigurations;
// Configuration Descriptor
// uint8_t interface_count; // bNumInterfaces alias
@@ -188,6 +197,18 @@ static usbh_class_driver_t const usbh_class_drivers[] = {
},
#endif
+ #if CFG_TUH_MIDI
+ {
+ .name = DRIVER_NAME("MIDI"),
+ .init = midih_init,
+ .deinit = midih_deinit,
+ .open = midih_open,
+ .set_config = midih_set_config,
+ .xfer_cb = midih_xfer_cb,
+ .close = midih_close
+ },
+ #endif
+
#if CFG_TUH_HUB
{
.name = DRIVER_NAME("HUB"),
@@ -214,7 +235,6 @@ static usbh_class_driver_t const usbh_class_drivers[] = {
};
enum { BUILTIN_DRIVER_COUNT = TU_ARRAY_SIZE(usbh_class_drivers) };
-enum { CONFIG_NUM = 1 }; // default to use configuration 1
// Additional class drivers implemented by application
tu_static usbh_class_driver_t const * _app_driver = NULL;
@@ -272,9 +292,10 @@ static struct {
tuh_xfer_cb_t complete_cb;
uintptr_t user_data;
- uint8_t daddr;
volatile uint8_t stage;
+ uint8_t daddr;
volatile uint16_t actual_len;
+ uint8_t failed_count;
} _ctrl_xfer;
typedef struct {
@@ -285,7 +306,6 @@ typedef struct {
CFG_TUH_MEM_SECTION static usbh_epbuf_t _usbh_epbuf;
//------------- Helper Function -------------//
-
TU_ATTR_ALWAYS_INLINE static inline usbh_device_t* get_device(uint8_t dev_addr) {
TU_VERIFY(dev_addr > 0 && dev_addr <= TOTAL_DEVICES, NULL);
return &_usbh_devices[dev_addr-1];
@@ -312,6 +332,15 @@ bool tuh_mounted(uint8_t dev_addr) {
return dev->configured;
}
+bool tuh_connected(uint8_t daddr) {
+ if (daddr == 0) {
+ return _dev0.enumerating; // dev0 is connected if still enumerating
+ } else {
+ const usbh_device_t* dev = get_device(daddr);
+ return dev && dev->connected;
+ }
+}
+
bool tuh_vid_pid_get(uint8_t dev_addr, uint16_t *vid, uint16_t *pid) {
*vid = *pid = 0;
@@ -438,7 +467,9 @@ bool tuh_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
}
bool tuh_deinit(uint8_t rhport) {
- if (!tuh_rhport_is_active(rhport)) return true;
+ if (!tuh_rhport_is_active(rhport)) {
+ return true;
+ }
// deinit host controller
hcd_int_disable(rhport);
@@ -484,13 +515,11 @@ bool tuh_task_event_ready(void) {
* This should be called periodically within the mainloop or rtos thread.
*
@code
- int main(void)
- {
+ int main(void) {
application_init();
tusb_init(0, TUSB_ROLE_HOST);
- while(1) // the mainloop
- {
+ while(1) { // the mainloop
application_code();
tuh_task(); // tinyusb host task
}
@@ -501,12 +530,14 @@ void tuh_task_ext(uint32_t timeout_ms, bool in_isr) {
(void) in_isr; // not implemented yet
// Skip if stack is not initialized
- if (!tuh_inited()) return;
+ if (!tuh_inited()) {
+ return;
+ }
// Loop until there is no more events in the queue
while (1) {
hcd_event_t event;
- if (!osal_queue_receive(_usbh_q, &event, timeout_ms)) return;
+ if (!osal_queue_receive(_usbh_q, &event, timeout_ms)) { return; }
switch (event.event_id) {
case HCD_EVENT_DEVICE_ATTACH:
@@ -635,17 +666,9 @@ static void _control_blocking_complete_cb(tuh_xfer_t* xfer) {
// TODO timeout_ms is not supported yet
bool tuh_control_xfer (tuh_xfer_t* xfer) {
- // EP0 with setup packet
- TU_VERIFY(xfer->ep_addr == 0 && xfer->setup);
-
- // Check if device is still connected (enumerating for dev0)
+ TU_VERIFY(xfer->ep_addr == 0 && xfer->setup); // EP0 with setup packet
const uint8_t daddr = xfer->daddr;
- if (daddr == 0) {
- TU_VERIFY(_dev0.enumerating);
- } else {
- const usbh_device_t* dev = get_device(daddr);
- TU_VERIFY(dev && dev->connected);
- }
+ TU_VERIFY(tuh_connected(daddr)); // Check if device is still connected (enumerating for dev0)
// pre-check to help reducing mutex lock
TU_VERIFY(_ctrl_xfer.stage == CONTROL_STAGE_IDLE);
@@ -653,14 +676,15 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) {
bool const is_idle = (_ctrl_xfer.stage == CONTROL_STAGE_IDLE);
if (is_idle) {
- _ctrl_xfer.stage = CONTROL_STAGE_SETUP;
- _ctrl_xfer.daddr = daddr;
- _ctrl_xfer.actual_len = 0;
+ _ctrl_xfer.stage = CONTROL_STAGE_SETUP;
+ _ctrl_xfer.daddr = daddr;
+ _ctrl_xfer.actual_len = 0;
+ _ctrl_xfer.failed_count = 0;
- _ctrl_xfer.buffer = xfer->buffer;
- _ctrl_xfer.complete_cb = xfer->complete_cb;
- _ctrl_xfer.user_data = xfer->user_data;
- _usbh_epbuf.request = (*xfer->setup);
+ _ctrl_xfer.buffer = xfer->buffer;
+ _ctrl_xfer.complete_cb = xfer->complete_cb;
+ _ctrl_xfer.user_data = xfer->user_data;
+ _usbh_epbuf.request = (*xfer->setup);
}
(void) osal_mutex_unlock(_usbh_mutex);
@@ -674,7 +698,7 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) {
TU_LOG_BUF_USBH(xfer->setup, 8);
if (xfer->complete_cb) {
- TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t const*) &_usbh_epbuf.request) );
+ TU_ASSERT(hcd_setup_send(rhport, daddr, (uint8_t const *) &_usbh_epbuf.request));
}else {
// blocking if complete callback is not provided
// change callback to internal blocking, and result as user argument
@@ -684,7 +708,7 @@ bool tuh_control_xfer (tuh_xfer_t* xfer) {
_ctrl_xfer.user_data = (uintptr_t) &result;
_ctrl_xfer.complete_cb = _control_blocking_complete_cb;
- TU_ASSERT( hcd_setup_send(rhport, daddr, (uint8_t*) &_usbh_epbuf.request) );
+ TU_ASSERT(hcd_setup_send(rhport, daddr, (uint8_t *) &_usbh_epbuf.request));
while (result == XFER_RESULT_INVALID) {
// Note: this can be called within an callback ie. part of tuh_task()
@@ -741,28 +765,46 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t
const uint8_t rhport = usbh_get_rhport(daddr);
tusb_control_request_t const * request = &_usbh_epbuf.request;
- if (XFER_RESULT_SUCCESS != result) {
- TU_LOG_USBH("[%u:%u] Control %s, xferred_bytes = %" PRIu32 "\r\n", rhport, daddr, result == XFER_RESULT_STALLED ? "STALLED" : "FAILED", xferred_bytes);
- TU_LOG_BUF_USBH(request, 8);
+ switch (result) {
+ case XFER_RESULT_STALLED:
+ TU_LOG_USBH("[%u:%u] Control STALLED, xferred_bytes = %" PRIu32 "\r\n", rhport, daddr, xferred_bytes);
+ TU_LOG_BUF_USBH(request, 8);
+ _control_xfer_complete(daddr, result);
+ break;
- // terminate transfer if any stage failed
- _control_xfer_complete(daddr, result);
- }else {
- switch(_ctrl_xfer.stage) {
- case CONTROL_STAGE_SETUP:
- if (request->wLength) {
- // DATA stage: initial data toggle is always 1
- _set_control_xfer_stage(CONTROL_STAGE_DATA);
- TU_ASSERT( hcd_edpt_xfer(rhport, daddr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength) );
- return true;
- }
+ case XFER_RESULT_FAILED:
+ if (tuh_connected(daddr) && _ctrl_xfer.failed_count < USBH_CONTROL_RETRY_MAX) {
+ TU_LOG_USBH("[%u:%u] Control FAILED %u/%u, retrying\r\n", rhport, daddr, _ctrl_xfer.failed_count+1, USBH_CONTROL_RETRY_MAX);
+ (void) osal_mutex_lock(_usbh_mutex, OSAL_TIMEOUT_WAIT_FOREVER);
+ _ctrl_xfer.stage = CONTROL_STAGE_SETUP;
+ _ctrl_xfer.failed_count++;
+ _ctrl_xfer.actual_len = 0; // reset actual_len
+ (void) osal_mutex_unlock(_usbh_mutex);
+
+ TU_ASSERT(hcd_setup_send(rhport, daddr, (uint8_t const *) request));
+ } else {
+ TU_LOG_USBH("[%u:%u] Control FAILED, xferred_bytes = %" PRIu32 "\r\n", rhport, daddr, xferred_bytes);
+ TU_LOG_BUF_USBH(request, 8);
+ _control_xfer_complete(daddr, result);
+ }
+ break;
+
+ case XFER_RESULT_SUCCESS:
+ switch(_ctrl_xfer.stage) {
+ case CONTROL_STAGE_SETUP:
+ if (request->wLength) {
+ // DATA stage: initial data toggle is always 1
+ _set_control_xfer_stage(CONTROL_STAGE_DATA);
+ TU_ASSERT( hcd_edpt_xfer(rhport, daddr, tu_edpt_addr(0, request->bmRequestType_bit.direction), _ctrl_xfer.buffer, request->wLength) );
+ return true;
+ }
TU_ATTR_FALLTHROUGH;
- case CONTROL_STAGE_DATA:
- if (request->wLength) {
- TU_LOG_USBH("[%u:%u] Control data:\r\n", rhport, daddr);
- TU_LOG_MEM_USBH(_ctrl_xfer.buffer, xferred_bytes, 2);
- }
+ case CONTROL_STAGE_DATA:
+ if (request->wLength) {
+ TU_LOG_USBH("[%u:%u] Control data:\r\n", rhport, daddr);
+ TU_LOG_MEM_USBH(_ctrl_xfer.buffer, xferred_bytes, 2);
+ }
_ctrl_xfer.actual_len = (uint16_t) xferred_bytes;
@@ -771,23 +813,26 @@ static bool usbh_control_xfer_cb (uint8_t daddr, uint8_t ep_addr, xfer_result_t
TU_ASSERT( hcd_edpt_xfer(rhport, daddr, tu_edpt_addr(0, 1 - request->bmRequestType_bit.direction), NULL, 0) );
break;
- case CONTROL_STAGE_ACK: {
- // Abort all pending transfers if SET_CONFIGURATION request
- // NOTE: should we force closing all non-control endpoints in the future?
- if (request->bRequest == TUSB_REQ_SET_CONFIGURATION && request->bmRequestType == 0x00) {
- for(uint8_t epnum=1; epnumbRequest == TUSB_REQ_SET_CONFIGURATION && request->bmRequestType == 0x00) {
+ for(uint8_t epnum=1; epnumclose(daddr);
+ if (driver) {
+ driver->close(daddr);
+ }
}
hcd_device_close(rhport, daddr);
@@ -1334,39 +1388,42 @@ enum {
ENUM_HUB_GET_STATUS_2,
ENUM_HUB_CLEAR_RESET_2,
ENUM_SET_ADDR,
-
ENUM_GET_DEVICE_DESC,
+ ENUM_GET_STRING_LANGUAGE_ID,
+ ENUM_GET_STRING_MANUFACTURER,
+ ENUM_GET_STRING_PRODUCT,
+ ENUM_GET_STRING_SERIAL,
ENUM_GET_9BYTE_CONFIG_DESC,
ENUM_GET_FULL_CONFIG_DESC,
ENUM_SET_CONFIG,
ENUM_CONFIG_DRIVER
};
-static bool enum_request_set_addr(void);
-static bool _parse_configuration_descriptor (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg);
+static bool enum_request_set_addr(tusb_desc_device_t const* desc_device);
+static bool enum_parse_configuration_desc (uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg);
static void enum_full_complete(void);
// process device enumeration
static void process_enumeration(tuh_xfer_t* xfer) {
- // Retry a few times with transfers in enumeration since device can be unstable when starting up
- enum {
- ATTEMPT_COUNT_MAX = 3,
- ATTEMPT_DELAY_MS = 100
- };
+ // Retry a few times while enumerating since device can be unstable when starting up
static uint8_t failed_count = 0;
+ if (XFER_RESULT_FAILED == xfer->result) {
+ enum {
+ ATTEMPT_COUNT_MAX = 3,
+ ATTEMPT_DELAY_MS = 100
+ };
- if (XFER_RESULT_SUCCESS != xfer->result) {
// retry if not reaching max attempt
+ failed_count++;
bool retry = _dev0.enumerating && (failed_count < ATTEMPT_COUNT_MAX);
- if ( retry ) {
- failed_count++;
+ if (retry) {
tusb_time_delay_ms_api(ATTEMPT_DELAY_MS); // delay a bit
- TU_LOG1("Enumeration attempt %u\r\n", failed_count);
+ TU_LOG1("Enumeration attempt %u/%u\r\n", failed_count+1, ATTEMPT_COUNT_MAX);
retry = tuh_control_xfer(xfer);
}
if (!retry) {
- enum_full_complete();
+ enum_full_complete(); // complete as failed
}
return;
@@ -1375,6 +1432,8 @@ static void process_enumeration(tuh_xfer_t* xfer) {
uint8_t const daddr = xfer->daddr;
uintptr_t const state = xfer->user_data;
+ usbh_device_t* dev = get_device(daddr);
+ uint16_t langid = 0x0409; // default is English
switch (state) {
#if CFG_TUH_HUB
@@ -1457,7 +1516,7 @@ static void process_enumeration(tuh_xfer_t* xfer) {
#endif
case ENUM_SET_ADDR:
- enum_request_set_addr();
+ enum_request_set_addr((tusb_desc_device_t*) _usbh_epbuf.ctrl);
break;
case ENUM_GET_DEVICE_DESC: {
@@ -1465,7 +1524,6 @@ static void process_enumeration(tuh_xfer_t* xfer) {
tusb_time_delay_ms_api(2);
const uint8_t new_addr = (uint8_t) tu_le16toh(xfer->setup->wValue);
-
usbh_device_t* new_dev = get_device(new_addr);
TU_ASSERT(new_dev,);
new_dev->addressed = 1;
@@ -1479,24 +1537,75 @@ static void process_enumeration(tuh_xfer_t* xfer) {
// Get full device descriptor
TU_LOG_USBH("Get Device Descriptor\r\n");
TU_ASSERT(tuh_descriptor_get_device(new_addr, _usbh_epbuf.ctrl, sizeof(tusb_desc_device_t),
- process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC),);
+ process_enumeration, ENUM_GET_STRING_LANGUAGE_ID),);
break;
}
- case ENUM_GET_9BYTE_CONFIG_DESC: {
- tusb_desc_device_t const* desc_device = (tusb_desc_device_t const*) _usbh_epbuf.ctrl;
- usbh_device_t* dev = get_device(daddr);
+ case ENUM_GET_STRING_LANGUAGE_ID: {
+ // save the received device descriptor
TU_ASSERT(dev,);
-
+ tusb_desc_device_t const* desc_device = (tusb_desc_device_t const*) _usbh_epbuf.ctrl;
dev->vid = desc_device->idVendor;
dev->pid = desc_device->idProduct;
dev->i_manufacturer = desc_device->iManufacturer;
dev->i_product = desc_device->iProduct;
dev->i_serial = desc_device->iSerialNumber;
+ dev->bNumConfigurations = desc_device->bNumConfigurations;
+ tuh_enum_descriptor_device_cb(daddr, desc_device); // callback
+
+ tuh_descriptor_get_string_langid(daddr, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE,
+ process_enumeration, ENUM_GET_STRING_MANUFACTURER);
+ break;
+ }
+
+ case ENUM_GET_STRING_MANUFACTURER: {
+ TU_ASSERT(dev,);
+ const tusb_desc_string_t* desc_langid = (tusb_desc_string_t const*) _usbh_epbuf.ctrl;
+ if (desc_langid->bLength >= 4) {
+ langid = tu_le16toh(desc_langid->utf16le[0]);
+ }
+ if (dev->i_manufacturer != 0) {
+ tuh_descriptor_get_string(daddr, dev->i_manufacturer, langid, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE,
+ process_enumeration, ENUM_GET_STRING_PRODUCT);
+ break;
+ } else {
+ TU_ATTR_FALLTHROUGH;
+ }
+ }
+
+ case ENUM_GET_STRING_PRODUCT: {
+ TU_ASSERT(dev,);
+ if (state == ENUM_GET_STRING_PRODUCT) {
+ langid = tu_le16toh(xfer->setup->wIndex); // if not fall through, get langid from previous setup packet
+ }
+ if (dev->i_product != 0) {
+ tuh_descriptor_get_string(daddr, dev->i_product, 0x0409, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE,
+ process_enumeration, ENUM_GET_STRING_SERIAL);
+ break;
+ } else {
+ TU_ATTR_FALLTHROUGH;
+ }
+ }
+
+ case ENUM_GET_STRING_SERIAL: {
+ TU_ASSERT(dev,);
+ if (state == ENUM_GET_STRING_SERIAL) {
+ langid = tu_le16toh(xfer->setup->wIndex); // if not fall through, get langid from previous setup packet
+ }
+ if (dev->i_serial != 0) {
+ tuh_descriptor_get_string(daddr, dev->i_serial, langid, _usbh_epbuf.ctrl, CFG_TUH_ENUMERATION_BUFSIZE,
+ process_enumeration, ENUM_GET_9BYTE_CONFIG_DESC);
+ break;
+ } else {
+ TU_ATTR_FALLTHROUGH;
+ }
+ }
+
+ case ENUM_GET_9BYTE_CONFIG_DESC: {
// Get 9-byte for total length
- uint8_t const config_idx = CONFIG_NUM - 1;
- TU_LOG_USBH("Get Configuration[0] Descriptor (9 bytes)\r\n");
+ uint8_t const config_idx = 0;
+ TU_LOG_USBH("Get Configuration[%u] Descriptor (9 bytes)\r\n", config_idx);
TU_ASSERT(tuh_descriptor_get_configuration(daddr, config_idx, _usbh_epbuf.ctrl, 9,
process_enumeration, ENUM_GET_FULL_CONFIG_DESC),);
break;
@@ -1506,34 +1615,42 @@ static void process_enumeration(tuh_xfer_t* xfer) {
uint8_t const* desc_config = _usbh_epbuf.ctrl;
// Use offsetof to avoid pointer to the odd/misaligned address
- uint16_t const total_len = tu_le16toh(
- tu_unaligned_read16(desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)));
+ uint16_t const total_len = tu_le16toh(tu_unaligned_read16(desc_config + offsetof(tusb_desc_configuration_t, wTotalLength)));
// TODO not enough buffer to hold configuration descriptor
TU_ASSERT(total_len <= CFG_TUH_ENUMERATION_BUFSIZE,);
// Get full configuration descriptor
- uint8_t const config_idx = CONFIG_NUM - 1;
- TU_LOG_USBH("Get Configuration[0] Descriptor\r\n");
+ uint8_t const config_idx = (uint8_t) tu_le16toh(xfer->setup->wIndex);
+ TU_LOG_USBH("Get Configuration[%u] Descriptor\r\n", config_idx);
TU_ASSERT(tuh_descriptor_get_configuration(daddr, config_idx, _usbh_epbuf.ctrl, total_len,
process_enumeration, ENUM_SET_CONFIG),);
break;
}
- case ENUM_SET_CONFIG:
- TU_ASSERT(tuh_configuration_set(daddr, CONFIG_NUM, process_enumeration, ENUM_CONFIG_DRIVER),);
+ case ENUM_SET_CONFIG: {
+ uint8_t config_idx = (uint8_t) tu_le16toh(xfer->setup->wIndex);
+ if (tuh_enum_descriptor_configuration_cb(daddr, config_idx, (const tusb_desc_configuration_t*) _usbh_epbuf.ctrl)) {
+ TU_ASSERT(tuh_configuration_set(daddr, config_idx+1, process_enumeration, ENUM_CONFIG_DRIVER),);
+ } else {
+ config_idx++;
+ TU_ASSERT(config_idx < dev->bNumConfigurations,);
+ TU_LOG_USBH("Get Configuration[%u] Descriptor (9 bytes)\r\n", config_idx);
+ TU_ASSERT(tuh_descriptor_get_configuration(daddr, config_idx, _usbh_epbuf.ctrl, 9,
+ process_enumeration, ENUM_GET_FULL_CONFIG_DESC),);
+ }
break;
+ }
case ENUM_CONFIG_DRIVER: {
TU_LOG_USBH("Device configured\r\n");
- usbh_device_t* dev = get_device(daddr);
TU_ASSERT(dev,);
dev->configured = 1;
// Parse configuration & set up drivers
// driver_open() must not make any usb transfer
- TU_ASSERT(_parse_configuration_descriptor(daddr, (tusb_desc_configuration_t*) _usbh_epbuf.ctrl),);
+ TU_ASSERT(enum_parse_configuration_desc(daddr, (tusb_desc_configuration_t*) _usbh_epbuf.ctrl),);
// Start the Set Configuration process for interfaces (itf = TUSB_INDEX_INVALID_8)
// Since driver can perform control transfer within its set_config, this is done asynchronously.
@@ -1544,14 +1661,11 @@ static void process_enumeration(tuh_xfer_t* xfer) {
}
default:
- // stop enumeration if unknown state
- enum_full_complete();
+ enum_full_complete(); // stop enumeration if unknown state
break;
}
}
-
-
static bool enum_new_device(hcd_event_t* event) {
_dev0.rhport = event->rhport;
_dev0.hub_addr = event->connection.hub_addr;
@@ -1621,9 +1735,7 @@ static uint8_t get_new_address(bool is_hub) {
return 0; // invalid address
}
-static bool enum_request_set_addr(void) {
- tusb_desc_device_t const* desc_device = (tusb_desc_device_t const*) _usbh_epbuf.ctrl;
-
+static bool enum_request_set_addr(tusb_desc_device_t const* desc_device) {
// Get new address
uint8_t const new_addr = get_new_address(desc_device->bDeviceClass == TUSB_CLASS_HUB);
TU_ASSERT(new_addr != 0);
@@ -1661,7 +1773,7 @@ static bool enum_request_set_addr(void) {
return true;
}
-static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) {
+static bool enum_parse_configuration_desc(uint8_t dev_addr, tusb_desc_configuration_t const* desc_cfg) {
usbh_device_t* dev = get_device(dev_addr);
uint16_t const total_len = tu_le16toh(desc_cfg->wTotalLength);
uint8_t const* desc_end = ((uint8_t const*) desc_cfg) + total_len;
@@ -1674,7 +1786,7 @@ static bool _parse_configuration_descriptor(uint8_t dev_addr, tusb_desc_configur
if ( 0 == tu_desc_len(p_desc) ) {
// A zero length descriptor indicates that the device is off spec (e.g. wrong wTotalLength).
// Parsed interfaces should still be usable
- TU_LOG_USBH("Encountered a zero-length descriptor after %u bytes\r\n", (uint32_t)p_desc - (uint32_t)desc_cfg);
+ TU_LOG_USBH("Encountered a zero-length descriptor after %" PRIu32 " bytes\r\n", (uint32_t)p_desc - (uint32_t)desc_cfg);
break;
}
@@ -1778,7 +1890,9 @@ void usbh_driver_set_config_complete(uint8_t dev_addr, uint8_t itf_num) {
TU_LOG_USBH("HUB address = %u is mounted\r\n", dev_addr);
}else {
// Invoke callback if available
- if (tuh_mount_cb) tuh_mount_cb(dev_addr);
+ if (tuh_mount_cb) {
+ tuh_mount_cb(dev_addr);
+ }
}
}
}
@@ -1788,8 +1902,9 @@ static void enum_full_complete(void) {
_dev0.enumerating = 0;
#if CFG_TUH_HUB
- // get next hub status
- if (_dev0.hub_addr) hub_edpt_status_xfer(_dev0.hub_addr);
+ if (_dev0.hub_addr) {
+ hub_edpt_status_xfer(_dev0.hub_addr); // get next hub status
+ }
#endif
}
diff --git a/src/host/usbh.h b/src/host/usbh.h
index 72c237573..4829a8183 100644
--- a/src/host/usbh.h
+++ b/src/host/usbh.h
@@ -33,10 +33,17 @@
#include "common/tusb_common.h"
+#if CFG_TUH_MAX3421
+#include "portable/analog/max3421/hcd_max3421.h"
+#endif
+
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
//--------------------------------------------------------------------+
+// Endpoint Bulk size depending on host mx speed
+#define TUH_EPSIZE_BULK_MPS (TUD_OPT_HIGH_SPEED ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS)
+
// forward declaration
struct tuh_xfer_s;
typedef struct tuh_xfer_s tuh_xfer_t;
@@ -96,6 +103,15 @@ typedef union {
// APPLICATION CALLBACK
//--------------------------------------------------------------------+
+// Invoked when enumeration get device descriptor
+// Device is not ready to communicate yet, application can copy the descriptor if needed
+void tuh_enum_descriptor_device_cb(uint8_t daddr, const tusb_desc_device_t *desc_device);
+
+// Invoked when enumeration get configuration descriptor
+// For multi-configuration device return false to skip, true to proceed with this configuration (may not be implemented yet)
+// Device is not ready to communicate yet, application can copy the descriptor if needed
+bool tuh_enum_descriptor_configuration_cb(uint8_t daddr, uint8_t cfg_index, const tusb_desc_configuration_t *desc_config);
+
// Invoked when a device is mounted (configured)
TU_ATTR_WEAK void tuh_mount_cb (uint8_t daddr);
@@ -146,8 +162,7 @@ bool tuh_inited(void);
void tuh_task_ext(uint32_t timeout_ms, bool in_isr);
// Task function should be called in main/rtos loop
-TU_ATTR_ALWAYS_INLINE static inline
-void tuh_task(void) {
+TU_ATTR_ALWAYS_INLINE static inline void tuh_task(void) {
tuh_task_ext(UINT32_MAX, false);
}
@@ -183,17 +198,19 @@ tusb_speed_t tuh_speed_get(uint8_t daddr);
// Check if device is connected and configured
bool tuh_mounted(uint8_t daddr);
+// Check if device is connected which mean device has at least 1 successful transfer
+// Note: It may not be addressed/configured/mounted yet
+bool tuh_connected(uint8_t daddr);
+
// Check if device is suspended
-TU_ATTR_ALWAYS_INLINE static inline
-bool tuh_suspended(uint8_t daddr) {
+TU_ATTR_ALWAYS_INLINE static inline bool tuh_suspended(uint8_t daddr) {
// TODO implement suspend & resume on host
(void) daddr;
return false;
}
// Check if device is ready to communicate with
-TU_ATTR_ALWAYS_INLINE static inline
-bool tuh_ready(uint8_t daddr) {
+TU_ATTR_ALWAYS_INLINE static inline bool tuh_ready(uint8_t daddr) {
return tuh_mounted(daddr) && !tuh_suspended(daddr);
}
@@ -214,6 +231,9 @@ bool tuh_edpt_xfer(tuh_xfer_t* xfer);
// Open a non-control endpoint
bool tuh_edpt_open(uint8_t daddr, tusb_desc_endpoint_t const * desc_ep);
+// Close a non-control endpoint, it will abort any pending transfer
+bool tuh_edpt_close(uint8_t daddr, uint8_t ep_addr);
+
// Abort a queued transfer. Note: it can only abort transfer that has not been started
// Return true if a queued transfer is aborted, false if there is no transfer to abort
bool tuh_edpt_abort_xfer(uint8_t daddr, uint8_t ep_addr);
@@ -261,6 +281,13 @@ bool tuh_descriptor_get_hid_report(uint8_t daddr, uint8_t itf_num, uint8_t desc_
bool tuh_descriptor_get_string(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len,
tuh_xfer_cb_t complete_cb, uintptr_t user_data);
+// Get language id string descriptor (control transfer)
+TU_ATTR_ALWAYS_INLINE static inline
+bool tuh_descriptor_get_string_langid(uint8_t daddr, void* buffer, uint16_t len,
+ tuh_xfer_cb_t complete_cb, uintptr_t user_data) {
+ return tuh_descriptor_get_string(daddr, 0, 0, buffer, len, complete_cb, user_data);
+}
+
// Get manufacturer string descriptor (control transfer)
// true on success, false if there is on-going control transfer or incorrect parameters
bool tuh_descriptor_get_manufacturer_string(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len,
@@ -300,6 +327,12 @@ uint8_t tuh_descriptor_get_hid_report_sync(uint8_t daddr, uint8_t itf_num, uint8
// return transfer result
uint8_t tuh_descriptor_get_string_sync(uint8_t daddr, uint8_t index, uint16_t language_id, void* buffer, uint16_t len);
+// Sync (blocking) version of tuh_descriptor_get_string_langid()
+TU_ATTR_ALWAYS_INLINE static inline
+uint8_t tuh_descriptor_get_string_langid_sync(uint8_t daddr, void* buffer, uint16_t len) {
+ return tuh_descriptor_get_string_sync(daddr, 0, 0, buffer, len);
+}
+
// Sync (blocking) version of tuh_descriptor_get_manufacturer_string()
// return transfer result
uint8_t tuh_descriptor_get_manufacturer_string_sync(uint8_t daddr, uint16_t language_id, void* buffer, uint16_t len);
diff --git a/src/host/usbh_pvt.h b/src/host/usbh_pvt.h
index 95de915e9..bfa1fb2ba 100644
--- a/src/host/usbh_pvt.h
+++ b/src/host/usbh_pvt.h
@@ -41,10 +41,6 @@
#define TU_LOG_INT_USBH(...) TU_LOG_INT(CFG_TUH_LOG_LEVEL, __VA_ARGS__)
#define TU_LOG_HEX_USBH(...) TU_LOG_HEX(CFG_TUH_LOG_LEVEL, __VA_ARGS__)
-enum {
- USBH_EPSIZE_BULK_MAX = (TUH_OPT_HIGH_SPEED ? TUSB_EPSIZE_BULK_HS : TUSB_EPSIZE_BULK_FS)
-};
-
//--------------------------------------------------------------------+
// Class Driver API
//--------------------------------------------------------------------+
@@ -83,8 +79,8 @@ void usbh_defer_func(osal_task_func_t func, void *param, bool in_isr);
bool usbh_edpt_xfer_with_callback(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes,
tuh_xfer_cb_t complete_cb, uintptr_t user_data);
-TU_ATTR_ALWAYS_INLINE
-static inline bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) {
+TU_ATTR_ALWAYS_INLINE static inline
+bool usbh_edpt_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) {
return usbh_edpt_xfer_with_callback(dev_addr, ep_addr, buffer, total_bytes, NULL, 0);
}
diff --git a/src/osal/osal_none.h b/src/osal/osal_none.h
index c93f7a86c..40e9bb83a 100644
--- a/src/osal/osal_none.h
+++ b/src/osal/osal_none.h
@@ -137,18 +137,6 @@ typedef osal_queue_def_t* osal_queue_t;
.ff = TU_FIFO_INIT(_name##_buf, _depth, _type, false) \
}
-// lock queue by disable USB interrupt
-TU_ATTR_ALWAYS_INLINE static inline void _osal_q_lock(osal_queue_t qhdl) {
- // disable dcd/hcd interrupt
- qhdl->interrupt_set(false);
-}
-
-// unlock queue
-TU_ATTR_ALWAYS_INLINE static inline void _osal_q_unlock(osal_queue_t qhdl) {
- // enable dcd/hcd interrupt
- qhdl->interrupt_set(true);
-}
-
TU_ATTR_ALWAYS_INLINE static inline osal_queue_t osal_queue_create(osal_queue_def_t* qdef) {
tu_fifo_clear(&qdef->ff);
return (osal_queue_t) qdef;
@@ -162,22 +150,22 @@ TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_delete(osal_queue_t qhdl) {
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_receive(osal_queue_t qhdl, void* data, uint32_t msec) {
(void) msec; // not used, always behave as msec = 0
- _osal_q_lock(qhdl);
- bool success = tu_fifo_read(&qhdl->ff, data);
- _osal_q_unlock(qhdl);
+ qhdl->interrupt_set(false);
+ const bool success = tu_fifo_read(&qhdl->ff, data);
+ qhdl->interrupt_set(true);
return success;
}
TU_ATTR_ALWAYS_INLINE static inline bool osal_queue_send(osal_queue_t qhdl, void const* data, bool in_isr) {
if (!in_isr) {
- _osal_q_lock(qhdl);
+ qhdl->interrupt_set(false);
}
- bool success = tu_fifo_write(&qhdl->ff, data);
+ const bool success = tu_fifo_write(&qhdl->ff, data);
if (!in_isr) {
- _osal_q_unlock(qhdl);
+ qhdl->interrupt_set(true);
}
return success;
diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c
index c5e924266..bb33200f2 100644
--- a/src/portable/analog/max3421/hcd_max3421.c
+++ b/src/portable/analog/max3421/hcd_max3421.c
@@ -252,28 +252,6 @@ static tuh_configure_max3421_t _tuh_cfg = {
.pinctl = 0, // default: negative edge interrupt
};
-//--------------------------------------------------------------------+
-// API: SPI transfer with MAX3421E
-// - spi_cs_api(), spi_xfer_api(), int_api(): must be implemented by application
-// - reg_read(), reg_write(): is implemented by this driver, can be used by application
-//--------------------------------------------------------------------+
-
-// API to control MAX3421 SPI CS
-extern void tuh_max3421_spi_cs_api(uint8_t rhport, bool active);
-
-// API to transfer data with MAX3421 SPI
-// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only
-extern bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes);
-
-// API to enable/disable MAX3421 INTR pin interrupt
-extern void tuh_max3421_int_api(uint8_t rhport, bool enabled);
-
-// API to read MAX3421's register. Implemented by TinyUSB
-uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr);
-
-// API to write MAX3421's register. Implemented by TinyUSB
-bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr);
-
//--------------------------------------------------------------------+
// SPI Commands and Helper
//--------------------------------------------------------------------+
@@ -632,6 +610,9 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * e
if (daddr == 0 && ep_num == 0) {
ep = &_hcd_data.ep[0];
}else {
+ if (NULL != find_ep_not_addr0(daddr, ep_num, ep_dir)) {
+ return true; // already opened
+ }
ep = allocate_ep();
TU_ASSERT(ep);
ep->daddr = daddr;
@@ -645,6 +626,21 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * e
return true;
}
+bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) {
+ (void) rhport;
+ uint8_t const ep_num = tu_edpt_number(ep_addr);
+ tusb_dir_t const ep_dir = tu_edpt_dir(ep_addr);
+ max3421_ep_t * ep = find_ep_not_addr0(daddr, ep_num, ep_dir);
+
+ if (!ep) {
+ return false; // not opened
+ }
+
+ tu_memclr(ep, sizeof(max3421_ep_t));
+
+ return true;
+}
+
/* The microcontroller repeatedly writes the SNDFIFO register R2 to load the FIFO with up to 64 data bytes.
* Then the microcontroller writes the SNDBC register, which this does three things:
* 1. Tells the MAX3421E SIE (Serial Interface Engine) how many bytes in the FIFO to send.
diff --git a/src/portable/analog/max3421/hcd_max3421.h b/src/portable/analog/max3421/hcd_max3421.h
new file mode 100644
index 000000000..4631fa21a
--- /dev/null
+++ b/src/portable/analog/max3421/hcd_max3421.h
@@ -0,0 +1,63 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2025 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 TUSB_HCD_MAX3421_H
+#define TUSB_HCD_MAX3421_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+//--------------------------------------------------------------------+
+// SPI transfer API with MAX3421E are implemented by application
+// - spi_cs_api(), spi_xfer_api(), int_api()
+//--------------------------------------------------------------------+
+
+// API to control MAX3421 SPI CS
+extern void tuh_max3421_spi_cs_api(uint8_t rhport, bool active);
+
+// API to transfer data with MAX3421 SPI
+// Either tx_buf or rx_buf can be NULL, which means transfer is write or read only
+extern bool tuh_max3421_spi_xfer_api(uint8_t rhport, uint8_t const* tx_buf, uint8_t* rx_buf, size_t xfer_bytes);
+
+// API to enable/disable MAX3421 INTR pin interrupt
+extern void tuh_max3421_int_api(uint8_t rhport, bool enabled);
+
+//--------------------------------------------------------------------+
+// API for read/write MAX3421 registers
+// are implemented by this driver, can be used by application
+//--------------------------------------------------------------------+
+
+// API to read MAX3421's register. Implemented by TinyUSB
+uint8_t tuh_max3421_reg_read(uint8_t rhport, uint8_t reg, bool in_isr);
+
+// API to write MAX3421's register. Implemented by TinyUSB
+bool tuh_max3421_reg_write(uint8_t rhport, uint8_t reg, uint8_t data, bool in_isr);
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c
index 01bbf62bf..7451f69a3 100644
--- a/src/portable/ehci/ehci.c
+++ b/src/portable/ehci/ehci.c
@@ -62,8 +62,7 @@
#define QHD_MAX (CFG_TUH_DEVICE_MAX*CFG_TUH_ENDPOINT_MAX + CFG_TUH_HUB)
#define QTD_MAX QHD_MAX
-typedef struct
-{
+typedef struct {
ehci_link_t period_framelist[FRAMELIST_SIZE];
// TODO only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist)
@@ -139,6 +138,12 @@ static ehci_qhd_t* qhd_get_from_addr (uint8_t dev_addr, uint8_t ep_addr);
static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc);
static void qhd_attach_qtd(ehci_qhd_t *qhd, ehci_qtd_t *qtd);
static void qhd_remove_qtd(ehci_qhd_t *qhd);
+TU_ATTR_ALWAYS_INLINE static inline bool qhd_is_periodic(ehci_qhd_t const *qhd) {
+ return qhd->int_smask != 0;
+}
+TU_ATTR_ALWAYS_INLINE static inline uint8_t qhd_ep_addr(ehci_qhd_t const *qhd) {
+ return tu_edpt_addr(qhd->ep_number, qhd->pid);
+}
TU_ATTR_ALWAYS_INLINE static inline ehci_qtd_t* qtd_control(uint8_t dev_addr);
TU_ATTR_ALWAYS_INLINE static inline ehci_qtd_t* qtd_find_free (void);
@@ -146,9 +151,10 @@ static void qtd_init (ehci_qtd_t* qtd, void const* buffer, uint16_t total_bytes)
TU_ATTR_ALWAYS_INLINE static inline ehci_link_t* list_get_period_head(uint8_t rhport, uint32_t interval_ms);
TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t* list_get_async_head(uint8_t rhport);
-TU_ATTR_ALWAYS_INLINE static inline void list_insert (ehci_link_t *current, ehci_link_t *new, uint8_t new_type);
TU_ATTR_ALWAYS_INLINE static inline ehci_link_t* list_next (ehci_link_t const *p_link);
-static void list_remove_qhd_by_daddr(ehci_link_t* list_head, uint8_t dev_addr);
+TU_ATTR_ALWAYS_INLINE static inline void list_insert (ehci_link_t *current, ehci_link_t *entry, uint8_t type);
+TU_ATTR_ALWAYS_INLINE static inline void list_remove(ehci_link_t* head, ehci_link_t* prev, ehci_qhd_t* qhd);
+static void list_remove_qhd_by_addr(ehci_link_t *list_head, uint8_t dev_addr, uint8_t ep_addr);
static void ehci_disable_schedule(ehci_registers_t* regs, bool is_period) {
// maybe have a timeout for status
@@ -175,15 +181,12 @@ static void ehci_enable_schedule(ehci_registers_t* regs, bool is_period) {
//--------------------------------------------------------------------+
// HCD API
//--------------------------------------------------------------------+
-
-uint32_t hcd_frame_number(uint8_t rhport)
-{
+uint32_t hcd_frame_number(uint8_t rhport) {
(void) rhport;
return (ehci_data.uframe_number + ehci_data.regs->frame_index) >> 3;
}
-void hcd_port_reset(uint8_t rhport)
-{
+void hcd_port_reset(uint8_t rhport) {
(void) rhport;
ehci_registers_t* regs = ehci_data.regs;
@@ -204,8 +207,7 @@ void hcd_port_reset(uint8_t rhport)
regs->portsc = portsc;
}
-void hcd_port_reset_end(uint8_t rhport)
-{
+void hcd_port_reset_end(uint8_t rhport) {
(void) rhport;
ehci_registers_t* regs = ehci_data.regs;
@@ -221,32 +223,29 @@ void hcd_port_reset_end(uint8_t rhport)
regs->portsc = portsc;
}
-bool hcd_port_connect_status(uint8_t rhport)
-{
+bool hcd_port_connect_status(uint8_t rhport) {
(void) rhport;
return ehci_data.regs->portsc_bm.current_connect_status;
}
-tusb_speed_t hcd_port_speed_get(uint8_t rhport)
-{
+tusb_speed_t hcd_port_speed_get(uint8_t rhport) {
(void) rhport;
return (tusb_speed_t) ehci_data.regs->portsc_bm.nxp_port_speed; // NXP specific port speed
}
// Close all opened endpoint belong to this device
-void hcd_device_close(uint8_t rhport, uint8_t daddr)
-{
+void hcd_device_close(uint8_t rhport, uint8_t daddr) {
// skip dev0
if (daddr == 0) {
return;
}
- // Remove from async list
- list_remove_qhd_by_daddr((ehci_link_t *) list_get_async_head(rhport), daddr);
+ // Remove from async list all endpoints of this device
+ list_remove_qhd_by_addr((ehci_link_t *) list_get_async_head(rhport), daddr, TUSB_INDEX_INVALID_8);
- // Remove from all interval period list
- for(uint8_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++) {
- list_remove_qhd_by_daddr((ehci_link_t *) &ehci_data.period_head_arr[i], daddr);
+ // Remove from all interval period list of this device
+ for (uint8_t i = 0; i < TU_ARRAY_SIZE(ehci_data.period_head_arr); i++) {
+ list_remove_qhd_by_addr((ehci_link_t *) &ehci_data.period_head_arr[i], daddr, TUSB_INDEX_INVALID_8);
}
// Async doorbell (EHCI 4.8.2 for operational details)
@@ -358,12 +357,10 @@ bool ehci_init(uint8_t rhport, uint32_t capability_reg, uint32_t operatial_reg)
}
#if 0
-static void ehci_stop(uint8_t rhport)
-{
+static void ehci_stop(uint8_t rhport) {
(void) rhport;
ehci_registers_t* regs = ehci_data.regs;
-
regs->command_bm.run_stop = 0;
// USB Spec: controller has to stop within 16 uframe = 2 frames
@@ -375,41 +372,46 @@ static void ehci_stop(uint8_t rhport)
// Endpoint API
//--------------------------------------------------------------------+
-bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc)
-{
- (void) rhport;
-
+bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) {
// TODO not support ISO yet
TU_ASSERT (ep_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS);
//------------- Prepare Queue Head -------------//
- ehci_qhd_t *p_qhd = (ep_desc->bEndpointAddress == 0) ? qhd_control(dev_addr) : qhd_find_free();
+ ehci_qhd_t *p_qhd;
+ if (ep_desc->bEndpointAddress == 0) {
+ p_qhd = qhd_control(dev_addr);
+ } else {
+ if (NULL != qhd_get_from_addr(dev_addr, ep_desc->bEndpointAddress)) {
+ return true; // already opened
+ }
+ p_qhd = qhd_find_free();
+ }
TU_ASSERT(p_qhd);
-
qhd_init(p_qhd, dev_addr, ep_desc);
- // control of dev0 is always present as async head
- if ( dev_addr == 0 ) return true;
+ // control of dev0 always exists as async head
+ if (dev_addr == 0) {
+ return true;
+ }
// Insert to list
ehci_link_t * list_head = NULL;
-
- switch (ep_desc->bmAttributes.xfer)
- {
+ switch (ep_desc->bmAttributes.xfer) {
case TUSB_XFER_CONTROL:
case TUSB_XFER_BULK:
- list_head = (ehci_link_t*) list_get_async_head(rhport);
- break;
+ list_head = (ehci_link_t *) list_get_async_head(rhport);
+ break;
case TUSB_XFER_INTERRUPT:
list_head = list_get_period_head(rhport, p_qhd->interval_ms);
- break;
+ break;
case TUSB_XFER_ISOCHRONOUS:
// TODO iso is not supported
- break;
+ break;
- default: break;
+ default:
+ break;
}
TU_ASSERT(list_head);
@@ -421,8 +423,23 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
return true;
}
-bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
-{
+bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) {
+ ehci_qhd_t* qhd = qhd_get_from_addr(daddr, ep_addr);
+ TU_VERIFY(qhd != NULL);
+
+ ehci_link_t * list_head;
+ if (qhd_is_periodic(qhd)) {
+ // interrupt endpoint
+ list_head = list_get_period_head(rhport, qhd->interval_ms);;
+ } else {
+ list_head = (ehci_link_t *) list_get_async_head(rhport);
+ }
+
+ list_remove_qhd_by_addr(list_head, daddr, ep_addr);
+ return true;
+}
+
+bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) {
(void) rhport;
ehci_qhd_t* qhd = &ehci_data.control[dev_addr].qhd;
@@ -444,14 +461,14 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet
return true;
}
-bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen)
-{
+bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) {
(void) rhport;
uint8_t const epnum = tu_edpt_number(ep_addr);
uint8_t const dir = tu_edpt_dir(ep_addr);
ehci_qhd_t* qhd = qhd_get_from_addr(dev_addr, ep_addr);
+ TU_VERIFY(qhd != NULL);
ehci_qtd_t* qtd;
if (epnum == 0) {
@@ -540,8 +557,7 @@ bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) {
// This isr mean it is safe to modify previously removed queue head from async list.
// In tinyusb, queue head is only removed when device is unplugged.
TU_ATTR_ALWAYS_INLINE static inline
-void async_advance_isr(uint8_t rhport)
-{
+void async_advance_isr(uint8_t rhport) {
(void) rhport;
ehci_qhd_t *qhd_pool = ehci_data.qhd_pool;
@@ -612,8 +628,7 @@ void qhd_xfer_complete_isr(ehci_qhd_t * qhd) {
}
TU_ATTR_ALWAYS_INLINE static inline
-void proccess_async_xfer_isr(ehci_qhd_t * const list_head)
-{
+void proccess_async_xfer_isr(ehci_qhd_t * const list_head) {
ehci_qhd_t *qhd = list_head;
do {
@@ -623,8 +638,7 @@ void proccess_async_xfer_isr(ehci_qhd_t * const list_head)
}
TU_ATTR_ALWAYS_INLINE static inline
-void process_period_xfer_isr(uint8_t rhport, uint32_t interval_ms)
-{
+void process_period_xfer_isr(uint8_t rhport, uint32_t interval_ms) {
uint32_t const period_1ms_addr = (uint32_t) list_get_period_head(rhport, 1u);
ehci_link_t next_link = *list_get_period_head(rhport, interval_ms);
@@ -726,51 +740,55 @@ TU_ATTR_ALWAYS_INLINE static inline ehci_link_t* list_next(ehci_link_t const *p_
return (ehci_link_t*) tu_align32(p_link->address);
}
-TU_ATTR_ALWAYS_INLINE static inline void list_insert(ehci_link_t *current, ehci_link_t *new, uint8_t new_type)
-{
- new->address = current->address;
- current->address = ((uint32_t) new) | (new_type << 1);
+TU_ATTR_ALWAYS_INLINE static inline void list_insert(ehci_link_t *current, ehci_link_t *entry, uint8_t type) {
+ entry->address = current->address;
+ current->address = ((uint32_t) entry) | (type << 1);
}
-// Remove all queue head belong to this device address
-static void list_remove_qhd_by_daddr(ehci_link_t* list_head, uint8_t dev_addr) {
- ehci_link_t* prev = list_head;
+// Remove a queue head from the list.
+// Per EHCI 4.8.2 the removed qhd's next is linked to list head (which always reachable by Host Controller)
+// TODO support iTD/siTD
+TU_ATTR_ALWAYS_INLINE static inline void list_remove(ehci_link_t* head, ehci_link_t* prev, ehci_qhd_t* qhd) {
+ // TODO deactivate all TD, wait for QHD to inactive before removal
+ prev->address = qhd->next.address;
+
+ // link the removed qhd's next to list head
+ qhd->next.address = ((uint32_t) head) | (EHCI_QTYPE_QHD << 1);
+
+ if (qhd_is_periodic(qhd)) {
+ // period list queue element is guarantee to be free in the next frame (1 ms)
+ qhd->used = 0;
+ } else {
+ // async list use async advance handshake. Mark as removing, will completely re-usable when async advance isr occurs
+ qhd->removing = 1;
+ }
+
+ hcd_dcache_clean(qhd, sizeof(ehci_qhd_t));
+ hcd_dcache_clean(prev, sizeof(ehci_qhd_t));
+}
+
+// Remove queue head belong to this device address
+static void list_remove_qhd_by_addr(ehci_link_t *list_head, uint8_t dev_addr, uint8_t ep_addr) {
+ ehci_link_t *prev = list_head;
while (prev && !prev->terminate) {
- ehci_qhd_t* qhd = (ehci_qhd_t*) (uintptr_t) list_next(prev);
+ ehci_qhd_t *qhd = (ehci_qhd_t *) (uintptr_t) list_next(prev);
// done if loop back to head
- if ( (uintptr_t) qhd == (uintptr_t) list_head) {
+ if ((uintptr_t) qhd == (uintptr_t) list_head) {
break;
}
- if ( qhd->dev_addr == dev_addr ) {
- // TODO deactivate all TD, wait for QHD to inactive before removal
- prev->address = qhd->next.address;
-
- // EHCI 4.8.2 link the removed qhd's next to async head (which always reachable by Host Controller)
- qhd->next.address = ((uint32_t) list_head) | (EHCI_QTYPE_QHD << 1);
-
- if ( qhd->int_smask )
- {
- // period list queue element is guarantee to be free in the next frame (1 ms)
- qhd->used = 0;
- }else
- {
- // async list use async advance handshake
- // mark as removing, will completely re-usable when async advance isr occurs
- qhd->removing = 1;
- }
-
- hcd_dcache_clean(qhd, sizeof(ehci_qhd_t));
- hcd_dcache_clean(prev, sizeof(ehci_qhd_t));
- }else {
+ // ep_addr is 0xff means all endpoints of this device address
+ if (qhd->dev_addr == dev_addr &&
+ (ep_addr == TUSB_INDEX_INVALID_8 || qhd_ep_addr(qhd) == ep_addr)) {
+ list_remove(list_head, prev, qhd);
+ } else {
prev = list_next(prev);
}
}
}
-
//--------------------------------------------------------------------+
// Queue Header helper
//--------------------------------------------------------------------+
@@ -782,8 +800,10 @@ TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t* qhd_control(uint8_t dev_addr) {
// Find a free queue head
TU_ATTR_ALWAYS_INLINE static inline ehci_qhd_t *qhd_find_free(void) {
- for ( uint32_t i = 0; i < QHD_MAX; i++ ) {
- if ( !ehci_data.qhd_pool[i].used ) return &ehci_data.qhd_pool[i];
+ for (uint32_t i = 0; i < QHD_MAX; i++) {
+ if (!ehci_data.qhd_pool[i].used) {
+ return &ehci_data.qhd_pool[i];
+ }
}
return NULL;
}
@@ -800,10 +820,9 @@ static ehci_qhd_t *qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr) {
}
ehci_qhd_t *qhd_pool = ehci_data.qhd_pool;
-
- for ( uint32_t i = 0; i < QHD_MAX; i++ ) {
- if ( (qhd_pool[i].dev_addr == dev_addr) &&
- ep_addr == tu_edpt_addr(qhd_pool[i].ep_number, qhd_pool[i].pid) ) {
+ for (uint32_t i = 0; i < QHD_MAX; i++) {
+ if ((qhd_pool[i].dev_addr == dev_addr) &&
+ ep_addr == qhd_ep_addr(&qhd_pool[i])) {
return &qhd_pool[i];
}
}
@@ -812,8 +831,7 @@ static ehci_qhd_t *qhd_get_from_addr(uint8_t dev_addr, uint8_t ep_addr) {
}
// Init queue head with endpoint descriptor
-static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc)
-{
+static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) {
// address 0 is used as async head, which always on the list --> cannot be cleared (ehci halted otherwise)
if (dev_addr != 0) {
tu_memclr(p_qhd, sizeof(ehci_qhd_t));
@@ -830,39 +848,43 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c
p_qhd->ep_number = tu_edpt_number(ep_desc->bEndpointAddress);
p_qhd->ep_speed = devtree_info.speed;
p_qhd->data_toggle_control= (xfer_type == TUSB_XFER_CONTROL) ? 1 : 0;
- p_qhd->head_list_flag = (dev_addr == 0) ? 1 : 0; // addr0's endpoint is the static asyn list head
+ p_qhd->head_list_flag = (dev_addr == 0) ? 1 : 0; // addr0's endpoint is the static async list head
p_qhd->max_packet_size = tu_edpt_packet_size(ep_desc);
p_qhd->fl_ctrl_ep_flag = ((xfer_type == TUSB_XFER_CONTROL) && (p_qhd->ep_speed != TUSB_SPEED_HIGH)) ? 1 : 0;
p_qhd->nak_reload = 0;
- // Bulk/Control -> smask = cmask = 0
- // TODO Isochronous
- if (TUSB_XFER_INTERRUPT == xfer_type)
- {
- if (TUSB_SPEED_HIGH == p_qhd->ep_speed)
- {
- TU_ASSERT( interval <= 16, );
- if ( interval < 4) // sub millisecond interval
- {
- p_qhd->interval_ms = 0;
- p_qhd->int_smask = (interval == 1) ? TU_BIN8(11111111) :
- (interval == 2) ? TU_BIN8(10101010) : TU_BIN8(01000100);
- }else
- {
- p_qhd->interval_ms = (uint8_t) tu_min16( 1 << (interval-4), 255 );
- p_qhd->int_smask = TU_BIT(interval % 8);
+ switch (xfer_type) {
+ case TUSB_XFER_CONTROL:
+ case TUSB_XFER_BULK:
+ p_qhd->int_smask = p_qhd->fl_int_cmask = 0;
+ break;
+
+ case TUSB_XFER_INTERRUPT:
+ if (TUSB_SPEED_HIGH == p_qhd->ep_speed) {
+ TU_ASSERT(interval <= 16, );
+ if (interval < 4) {
+ // sub millisecond interval
+ p_qhd->interval_ms = 0;
+ p_qhd->int_smask = (interval == 1) ? TU_BIN8(11111111) :
+ (interval == 2) ? TU_BIN8(10101010): TU_BIN8(01000100);
+ } else {
+ p_qhd->interval_ms = (uint8_t) tu_min16(1 << (interval - 4), 255);
+ p_qhd->int_smask = TU_BIT(interval % 8);
+ }
+ } else {
+ TU_ASSERT(0 != interval, );
+ // Full/Low: 4.12.2.1 (EHCI) case 1 schedule start split at 1 us & complete split at 2,3,4 uframes
+ p_qhd->int_smask = 0x01;
+ p_qhd->fl_int_cmask = TU_BIN8(11100);
+ p_qhd->interval_ms = interval;
}
- }else
- {
- TU_ASSERT( 0 != interval, );
- // Full/Low: 4.12.2.1 (EHCI) case 1 schedule start split at 1 us & complete split at 2,3,4 uframes
- p_qhd->int_smask = 0x01;
- p_qhd->fl_int_cmask = TU_BIN8(11100);
- p_qhd->interval_ms = interval;
- }
- }else
- {
- p_qhd->int_smask = p_qhd->fl_int_cmask = 0;
+ break;
+
+ case TUSB_XFER_ISOCHRONOUS:
+ // TODO not support ISO yet
+ break;
+
+ default: break;
}
p_qhd->fl_hub_addr = devtree_info.hub_addr;
@@ -880,8 +902,7 @@ static void qhd_init(ehci_qhd_t *p_qhd, uint8_t dev_addr, tusb_desc_endpoint_t c
p_qhd->qtd_overlay.next.terminate = 1;
p_qhd->qtd_overlay.alternate.terminate = 1;
- if (TUSB_XFER_BULK == xfer_type && p_qhd->ep_speed == TUSB_SPEED_HIGH && p_qhd->pid == EHCI_PID_OUT)
- {
+ if (TUSB_XFER_BULK == xfer_type && p_qhd->ep_speed == TUSB_SPEED_HIGH && p_qhd->pid == EHCI_PID_OUT) {
p_qhd->qtd_overlay.ping_err = 1; // do PING for Highspeed Bulk OUT, EHCI section 4.11
}
}
diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h
index 457adc1d3..87659701b 100644
--- a/src/portable/ehci/ehci.h
+++ b/src/portable/ehci/ehci.h
@@ -49,15 +49,14 @@
// TODO merge OHCI with EHCI
enum {
- EHCI_MAX_ITD = 4,
+ EHCI_MAX_ITD = 4,
EHCI_MAX_SITD = 16
};
//--------------------------------------------------------------------+
// EHCI Data Structure
//--------------------------------------------------------------------+
-enum
-{
+enum {
EHCI_QTYPE_ITD = 0 ,
EHCI_QTYPE_QHD ,
EHCI_QTYPE_SITD ,
@@ -65,8 +64,7 @@ enum
};
/// EHCI PID
-enum
-{
+enum {
EHCI_PID_OUT = 0 ,
EHCI_PID_IN ,
EHCI_PID_SETUP
@@ -74,187 +72,182 @@ enum
/// Link pointer
typedef union {
- uint32_t address;
- struct {
- uint32_t terminate : 1;
- uint32_t type : 2;
- };
-}ehci_link_t;
+ uint32_t address;
+ struct {
+ uint32_t terminate : 1;
+ uint32_t type : 2;
+ };
+} ehci_link_t;
TU_VERIFY_STATIC( sizeof(ehci_link_t) == 4, "size is not correct" );
/// Queue Element Transfer Descriptor
/// Qtd is used to declare overlay in ehci_qhd_t -> cannot be declared with TU_ATTR_ALIGNED(32)
-typedef struct
-{
- // Word 0: Next QTD Pointer
- ehci_link_t next;
+typedef struct {
+ // Word 0 Next QTD Pointer
+ ehci_link_t next;
- // Word 1: Alternate Next QTD Pointer (not used)
- union{
- ehci_link_t alternate;
- struct {
- uint32_t : 5;
- uint32_t used : 1;
- uint32_t : 10;
- uint32_t expected_bytes : 16;
- };
- };
+ // Word 1 Alternate Next QTD Pointer (not used)
+ union {
+ ehci_link_t alternate;
+ struct {
+ uint32_t : 5;
+ uint32_t used : 1;
+ uint32_t : 10;
+ uint32_t expected_bytes : 16;
+ };
+ };
- // Word 2: qTQ Token
- volatile uint32_t ping_err : 1 ; ///< For Highspeed: 0 Out, 1 Ping. Full/Slow used as error indicator
- volatile uint32_t non_hs_split_state : 1 ; ///< Used by HC to track the state of split transaction
- volatile uint32_t non_hs_missed_uframe : 1 ; ///< HC misses a complete split transaction
- volatile uint32_t xact_err : 1 ; ///< Error (Timeout, CRC, Bad PID ... )
- volatile uint32_t babble_err : 1 ; ///< Babble detected, also set Halted bit to 1
- volatile uint32_t buffer_err : 1 ; ///< Data overrun/underrun error
- volatile uint32_t halted : 1 ; ///< Serious error or STALL received
- volatile uint32_t active : 1 ; ///< Start transfer, clear by HC when complete
+ // Word 2 qTQ Token
+ volatile uint32_t ping_err : 1; // For Highspeed: 0 Out, 1 Ping. Full/Slow used as error indicator
+ volatile uint32_t non_hs_split_state : 1; // Used by HC to track the state of split transaction
+ volatile uint32_t non_hs_missed_uframe : 1; // HC misses a complete split transaction
+ volatile uint32_t xact_err : 1; // Error (Timeout, CRC, Bad PID ... )
+ volatile uint32_t babble_err : 1; // Babble detected, also set Halted bit to 1
+ volatile uint32_t buffer_err : 1; // Data overrun/underrun error
+ volatile uint32_t halted : 1; // Serious error or STALL received
+ volatile uint32_t active : 1; // Start transfer, clear by HC when complete
- uint32_t pid : 2 ; ///< 0: OUT, 1: IN, 2 Setup
- volatile uint32_t err_count : 2 ; ///< Error Counter of consecutive errors
- volatile uint32_t current_page : 3 ; ///< Index into the qTD buffer pointer list
- uint32_t int_on_complete : 1 ; ///< Interrupt on complete
- volatile uint32_t total_bytes : 15 ; ///< Transfer bytes, decreased during transaction
- volatile uint32_t data_toggle : 1 ; ///< Data Toggle bit
+ uint32_t pid : 2; // 0: OUT, 1: IN, 2 Setup
+ volatile uint32_t err_count : 2; // Error Counter of consecutive errors
+ volatile uint32_t current_page : 3; // Index into the qTD buffer pointer list
+ uint32_t int_on_complete : 1; // Interrupt on complete
+ volatile uint32_t total_bytes : 15; // Transfer bytes, decreased during transaction
+ volatile uint32_t data_toggle : 1; // Data Toggle bit
-
- /// Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address. The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page
- uint32_t buffer[5];
+ // Buffer Page Pointer List, Each element in the list is a 4K page aligned, physical memory address.
+ // The lower 12 bits in each pointer are reserved (except for the first one) as each memory pointer must reference the start of a 4K page
+ uint32_t buffer[5];
} ehci_qtd_t;
TU_VERIFY_STATIC( sizeof(ehci_qtd_t) == 32, "size is not correct" );
/// Queue Head
-typedef struct TU_ATTR_ALIGNED(32)
-{
- // Word 0: Next QHD
- ehci_link_t next;
+typedef struct TU_ATTR_ALIGNED(32) {
+ // Word 0 Next QHD
+ ehci_link_t next;
- // Word 1: Endpoint Characteristics
- uint32_t dev_addr : 7 ; ///< device address
- uint32_t fl_inactive_next_xact : 1 ; ///< Only valid for Periodic with Full/Slow speed
- uint32_t ep_number : 4 ; ///< EP number
- uint32_t ep_speed : 2 ; ///< 0: Full, 1: Low, 2: High
- uint32_t data_toggle_control : 1 ; ///< 0: use DT in qHD, 1: use DT in qTD
- uint32_t head_list_flag : 1 ; ///< Head of the queue
- uint32_t max_packet_size : 11 ; ///< Max packet size
- uint32_t fl_ctrl_ep_flag : 1 ; ///< 1 if is Full/Low speed control endpoint
- uint32_t nak_reload : 4 ; ///< Used by HC
+ // Word 1 Endpoint Characteristics
+ uint32_t dev_addr : 7; // device address
+ uint32_t fl_inactive_next_xact : 1; // Only valid for Periodic with Full/Slow speed
+ uint32_t ep_number : 4; // EP number
+ uint32_t ep_speed : 2; // Full (0), Low (1), High (2)
+ uint32_t data_toggle_control : 1; // 0 use DT in qHD, 1 use DT in qTD
+ uint32_t head_list_flag : 1; // Head of the queue
+ uint32_t max_packet_size : 11; // Max packet size
+ uint32_t fl_ctrl_ep_flag : 1; // 1 if is Full/Low speed control endpoint
+ uint32_t nak_reload : 4; // Used by HC
- // Word 2: Endpoint Capabilities
- uint32_t int_smask : 8 ; ///< Interrupt Schedule Mask
- uint32_t fl_int_cmask : 8 ; ///< Split Completion Mask for Full/Slow speed
- uint32_t fl_hub_addr : 7 ; ///< Hub Address for Full/Slow speed
- uint32_t fl_hub_port : 7 ; ///< Hub Port for Full/Slow speed
- uint32_t mult : 2 ; ///< Transaction per micro frame
+ // Word 2 Endpoint Capabilities
+ uint32_t int_smask : 8; // Interrupt Schedule Mask
+ uint32_t fl_int_cmask : 8; // Split Completion Mask for Full/Slow speed
+ uint32_t fl_hub_addr : 7; // Hub Address for Full/Slow speed
+ uint32_t fl_hub_port : 7; // Hub Port for Full/Slow speed
+ uint32_t mult : 2; // Transaction per micro frame
- // Word 3: Current qTD Pointer
- volatile uint32_t qtd_addr;
+ // Word 3 Current qTD Pointer
+ volatile uint32_t qtd_addr;
- // Word 4-11: Transfer Overlay
- volatile ehci_qtd_t qtd_overlay;
+ // Word 4-11 Transfer Overlay
+ volatile ehci_qtd_t qtd_overlay;
- //--------------------------------------------------------------------+
- /// Due to the fact QHD is 32 bytes aligned but occupies only 48 bytes
- /// thus there are 16 bytes padding free that we can make use of.
//--------------------------------------------------------------------+
- uint8_t used;
- uint8_t removing; // removed from asyn list, waiting for async advance
- uint8_t pid;
- uint8_t interval_ms; // polling interval in frames (or millisecond)
+ /// Due to the fact QHD is 32 bytes aligned but occupies only 48 bytes
+ /// thus there are 16 bytes padding free that we can make use of.
+ //--------------------------------------------------------------------+
+ uint8_t used;
+ uint8_t removing;// removed from asyn list, waiting for async advance
+ uint8_t pid;
+ uint8_t interval_ms;// polling interval in frames (or millisecond)
- uint8_t TU_RESERVED[4];
+ uint8_t TU_RESERVED[4];
// Attached TD management, note usbh will only queue 1 TD per QHD.
// buffer for dcache invalidate since td's buffer is modified by HC and finding initial buffer address is not trivial
uint32_t attached_buffer;
- ehci_qtd_t * volatile attached_qtd;
+ ehci_qtd_t *volatile attached_qtd;
} ehci_qhd_t;
-
TU_VERIFY_STATIC( sizeof(ehci_qhd_t) == 64, "size is not correct" );
/// Highspeed Isochronous Transfer Descriptor (section 3.3)
typedef struct TU_ATTR_ALIGNED(32) {
- // Word 0: Next Link Pointer
- ehci_link_t next;
+ // Word 0: Next Link Pointer
+ ehci_link_t next;
- // Word 1-8: iTD Transaction Status and Control List
- struct {
- // iTD Control
- volatile uint32_t offset : 12 ; ///< This field is a value that is an offset, expressed in bytes, from the beginning of a buffer.
- volatile uint32_t page_select : 3 ; ///< These bits are set by software to indicate which of the buffer page pointers the offset field in this slot should be concatenated to produce the starting memory address for this transaction. The valid range of values for this field is 0 to 6
- uint32_t int_on_complete : 1 ; ///< If this bit is set to a one, it specifies that when this transaction completes, the Host Controller should issue an interrupt at the next interrupt threshold
- volatile uint32_t length : 12 ; ///< For an OUT, this field is the number of data bytes the host controller will send during the transaction. The host controller is not required to update this field to reflect the actual number of bytes transferred during the transfer
- ///< For an IN, the initial value of the field is the number of bytes the host expects the endpoint to deliver. During the status update, the host controller writes back the number of bytes successfully received. The value in this register is the actual byte count
- // iTD Status
- volatile uint32_t error : 1 ; ///< Set to a one by the Host Controller during status update in the case where the host did not receive a valid response from the device (Timeout, CRC, Bad PID, etc.). This bit may only be set for isochronous IN transactions.
- volatile uint32_t babble_err : 1 ; ///< Set to a 1 by the Host Controller during status update when a babble is detected during the transaction
- volatile uint32_t buffer_err : 1 ; ///< Set to a 1 by the Host Controller during status update to indicate that the Host Controller is unable to keep up with the reception of incoming data (overrun) or is unable to supply data fast enough during transmission (underrun).
- volatile uint32_t active : 1 ; ///< Set to 1 by software to enable the execution of an isochronous transaction by the Host Controller
- } xact[8];
+ // Word 1-8: iTD Transaction Status and Control List
+ struct {
+ // iTD Control
+ volatile uint32_t offset : 12; // offset in bytes, from the beginning of a buffer.
+ volatile uint32_t page_select : 3; // buffer page pointers the offset field in this slot should be concatenated to produce the starting memory address for this transaction. The valid range of values for this field is 0 to 6
+ uint32_t int_on_complete : 1; // If this bit is set to a one, it specifies that when this transaction completes, the Host Controller should issue an interrupt at the next interrupt threshold
+ volatile uint32_t length : 12; // For an OUT, this field is the number of data bytes the host controller will send during the transaction. The host controller is not required to update this field to reflect the actual number of bytes transferred during the transfer
+ // For an IN, the initial value of the field is the number of bytes the host expects the endpoint to deliver. During the status update, the host controller writes back the number of bytes successfully received. The value in this register is the actual byte count
+ // iTD Status
+ volatile uint32_t error : 1; // Set to a one by the Host Controller during status update in the case where the host did not receive a valid response from the device (Timeout, CRC, Bad PID, etc.). This bit may only be set for isochronous IN transactions.
+ volatile uint32_t babble_err : 1; // Set to a 1 by the Host Controller during status update when a babble is detected during the transaction
+ volatile uint32_t buffer_err : 1; // Set to a 1 by the Host Controller during status update to indicate that the Host Controller is unable to keep up with the reception of incoming data (overrun) or is unable to supply data fast enough during transmission (underrun).
+ volatile uint32_t active : 1; // Set to 1 by software to enable the execution of an isochronous transaction by the Host Controller
+ } xact[8];
- // Word 9-15 Buffer Page Pointer List (Plus)
- uint32_t BufferPointer[7];
+ // Word 9-15 Buffer Page Pointer List (Plus)
+ uint32_t BufferPointer[7];
-// // FIXME: Store meta data into buffer pointer reserved for saving memory
-// /*---------- HCD Area ----------*/
-// uint32_t used;
-// uint32_t IhdIdx;
-// uint32_t reserved[6];
+ // FIXME: Store meta data into buffer pointer reserved for saving memory
+ //---------- HCD Area ----------
+ // uint32_t used;
+ // uint32_t IhdIdx;
+ // uint32_t reserved[6];
} ehci_itd_t;
-
TU_VERIFY_STATIC( sizeof(ehci_itd_t) == 64, "size is not correct" );
/// Split (Full-Speed) Isochronous Transfer Descriptor
-typedef struct TU_ATTR_ALIGNED(32)
-{
+typedef struct TU_ATTR_ALIGNED(32) {
// Word 0: Next Link Pointer
- ehci_link_t next;
+ ehci_link_t next;
- // Word 1: siTD Endpoint Characteristics
- uint32_t dev_addr : 7; ///< This field selects the specific device serving as the data source or sink.
- uint32_t : 1; ///< reserved
- uint32_t ep_number : 4; ///< This 4-bit field selects the particular endpoint number on the device serving as the data source or sink.
- uint32_t : 4; ///< This field is reserved and should be set to zero.
- uint32_t hub_addr : 7; ///< This field holds the device address of the transaction translators’ hub.
- uint32_t : 1; ///< reserved
- uint32_t port_number : 7; ///< This field is the port number of the recipient transaction translator.
- uint32_t direction : 1; ///< 0 = OUT; 1 = IN. This field encodes whether the full-speed transaction should be an IN or OUT.
+ // Word 1: siTD Endpoint Characteristics
+ uint32_t dev_addr : 7; ///< This field selects the specific device serving as the data source or sink.
+ uint32_t : 1; ///< reserved
+ uint32_t ep_number : 4; ///< This 4-bit field selects the particular endpoint number on the device serving as the data source or sink.
+ uint32_t : 4; ///< This field is reserved and should be set to zero.
+ uint32_t hub_addr : 7; ///< This field holds the device address of the transaction translators’ hub.
+ uint32_t : 1; ///< reserved
+ uint32_t port_number : 7; ///< This field is the port number of the recipient transaction translator.
+ uint32_t direction : 1; ///< 0 = OUT; 1 = IN. This field encodes whether the full-speed transaction should be an IN or OUT.
- // Word 2: Micro-frame Schedule Control
- uint8_t int_smask ; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute complete-split transactions
- uint8_t fl_int_cmask; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute start-split transactions.
- uint16_t reserved ; ///< reserved
+ // Word 2: Micro-frame Schedule Control
+ uint8_t int_smask ; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute complete-split transactions
+ uint8_t fl_int_cmask; ///< This field (along with the Activeand SplitX-statefields in the Statusbyte) are used to determine during which micro-frames the host controller should execute start-split transactions.
+ uint16_t reserved ; ///< reserved
- // Word 3: siTD Transfer Status and Control
- // Status [7:0] TODO identical to qTD Token'status --> refactor later
- volatile uint32_t : 1 ; // reserved
- volatile uint32_t split_state : 1 ;
- volatile uint32_t missed_uframe : 1 ;
- volatile uint32_t xact_err : 1 ;
- volatile uint32_t babble_err : 1 ;
- volatile uint32_t buffer_err : 1 ;
- volatile uint32_t error : 1 ;
- volatile uint32_t active : 1 ;
- // Micro-frame Schedule Control
- volatile uint32_t cmask_progress : 8 ; ///< This field is used by the host controller to record which split-completes have been executed. See Section 4.12.3.3.2 for behavioral requirements.
- volatile uint32_t total_bytes : 10 ; ///< This field is initialized by software to the total number of bytes expected in this transfer. Maximum value is 1023
- volatile uint32_t : 4 ; ///< reserved
- volatile uint32_t page_select : 1 ; ///< Used to indicate which data page pointer should be concatenated with the CurrentOffsetfield to construct a data buffer pointer
- uint32_t int_on_complete : 1 ; ///< Do not interrupt when transaction is complete. 1 = Do interrupt when transaction is complete
- uint32_t : 0 ; // padding to the end of current storage unit
+ // Word 3: siTD Transfer Status and Control
+ // Status [7:0] TODO identical to qTD Token'status --> refactor later
+ volatile uint32_t : 1 ; // reserved
+ volatile uint32_t split_state : 1 ;
+ volatile uint32_t missed_uframe : 1 ;
+ volatile uint32_t xact_err : 1 ;
+ volatile uint32_t babble_err : 1 ;
+ volatile uint32_t buffer_err : 1 ;
+ volatile uint32_t error : 1 ;
+ volatile uint32_t active : 1 ;
+ // Micro-frame Schedule Control
+ volatile uint32_t cmask_progress : 8 ; ///< This field is used by the host controller to record which split-completes have been executed. See Section 4.12.3.3.2 for behavioral requirements.
+ volatile uint32_t total_bytes : 10 ; ///< This field is initialized by software to the total number of bytes expected in this transfer. Maximum value is 1023
+ volatile uint32_t : 4 ; ///< reserved
+ volatile uint32_t page_select : 1 ; ///< Used to indicate which data page pointer should be concatenated with the CurrentOffsetfield to construct a data buffer pointer
+ uint32_t int_on_complete : 1 ; ///< Do not interrupt when transaction is complete. 1 = Do interrupt when transaction is complete
+ uint32_t : 0 ; // padding to the end of current storage unit
- /// Word 4-5: Buffer Pointer List
- uint32_t buffer[2]; // buffer[1] TP: Transaction Position - T-Count: Transaction Count
+ /// Word 4-5: Buffer Pointer List
+ uint32_t buffer[2]; // buffer[1] TP: Transaction Position - T-Count: Transaction Count
- /*---------- Word 6 ----------*/
- ehci_link_t back;
+ /*---------- Word 6 ----------*/
+ ehci_link_t back;
- /// SITD is 32-byte aligned but occupies only 28 --> 4 bytes for storing extra data
- uint8_t used;
- uint8_t ihd_idx;
- uint8_t reserved2[2];
+ /// SITD is 32-byte aligned but occupies only 28 --> 4 bytes for storing extra data
+ uint8_t used;
+ uint8_t ihd_idx;
+ uint8_t reserved2[2];
} ehci_sitd_t;
TU_VERIFY_STATIC( sizeof(ehci_sitd_t) == 32, "size is not correct" );
@@ -315,8 +308,7 @@ enum {
EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE
};
-typedef volatile struct
-{
+typedef volatile struct {
union {
uint32_t command; // 0x00
diff --git a/src/portable/mentor/musb/hcd_musb.c b/src/portable/mentor/musb/hcd_musb.c
index 1c0740193..811043d74 100644
--- a/src/portable/mentor/musb/hcd_musb.c
+++ b/src/portable/mentor/musb/hcd_musb.c
@@ -804,6 +804,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
return true;
}
+bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) {
+ (void) rhport; (void) daddr; (void) ep_addr;
+ return false; // TODO not implemented yet
+}
+
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen)
{
(void)rhport;
diff --git a/src/portable/microchip/pic/README.md b/src/portable/microchip/pic/README.md
new file mode 100644
index 000000000..7ba6a4a96
--- /dev/null
+++ b/src/portable/microchip/pic/README.md
@@ -0,0 +1,51 @@
+# Microchip PIC Chipidea FS Driver
+
+This driver adds support for Microchip PIC microcontrollers with full-speed Chipidea USB peripheral to the TinyUSB stack. It supports the following families:
+
+- PIC32MX (untested)
+- PIC32MM
+- PIC32MK (untested)
+- PIC24FJ
+- PIC24EP (untested)
+- dsPIC33EP (untested)
+
+Currently only the device mode is supported.
+
+
+## Important Notes
+
+### Handling of shared VBUS & GPIO pin
+
+Some PICs have the USB VBUS pin bonded with a GPIO pin in the chip package. This driver does **NOT** handle the potential conflict between the VBUS and GPIO functionalities.
+
+Developers must ensure that the GPIO pin is tristated when the VBUS pin is managed by the USB peripheral in order to prevent damaging the chip.
+
+This design choice allows developers the flexibility to use the GPIO functionality for controlling VBUS in device mode if desired.
+
+
+## TODO
+
+### Handle USB remote wakeup timing correctly
+
+The Chipidea FS IP doesn't handle the RESUME signal automatically and it must be managed in software. It needs to be asserted for exactly 10ms, and this is impossible to do without per-device support due to BSP differences. For now, a simple for-based loop is used.
+
+### 8-bit PIC support
+
+The 8-bit PICs also uses the Chipidea FS IP. Technically it's possible to support them as well.
+
+Possible difficulties:
+- Memory size constraints (1KB/8KB ballpark)
+- A third BDT layout (now we have two)
+- Different compiler-specific directives
+- Compiler bugs if you use SDCC
+
+
+## Author
+[ReimuNotMoe](https://github.com/ReimuNotMoe) at SudoMaker, Ltd.
+
+
+## Credits
+
+This driver is based on:
+- Microchip's USB driver (usb_device.c)
+- TinyUSB's NXP KHCI driver (dcd_khci.c)
diff --git a/src/portable/microchip/pic/dcd_pic.c b/src/portable/microchip/pic/dcd_pic.c
index d40c4794a..b4a698199 100644
--- a/src/portable/microchip/pic/dcd_pic.c
+++ b/src/portable/microchip/pic/dcd_pic.c
@@ -1,8 +1,11 @@
/*
* The MIT License (MIT)
*
- * Copyright (c) 2020 Koji Kitayama
- * Copyright (c) 2022 Reimu NotMoe
+ * Copyright (c) 2022-2024 SudoMaker, Ltd.
+ * Author: Mike Yang (Reimu NotMoe)
+ *
+ * Based on usb_device.c - Copyright (c) 2015 Microchip Technology Inc.
+ * Based on dcd_khci.c - Copyright (c) 2020 Koji Kitayama
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -313,12 +316,23 @@ static void prepare_next_setup_packet(uint8_t rhport)
{
const unsigned out_odd = _dcd.endpoint[0][0].odd;
const unsigned in_odd = _dcd.endpoint[0][1].odd;
- TU_ASSERT(0 == _dcd.bdt[0][0][out_odd].own, );
+
+ // Abandon any previous control transfers that might have been using EP0.
+ // Ordinarily, nothing actually needs abandoning, since the previous control
+ // transfer would have completed successfully prior to the host sending the
+ // next SETUP packet. However, in a timeout error case, or after an EP0
+ // STALL event, one or more UOWN bits might still be set. If so, we should
+ // clear the UOWN bits, so the EP0 IN/OUT endpoints are in a known inactive
+ // state, ready for re-arming by the `dcd_edpt_xfer' function that will be
+ // called next.
_dcd.bdt[0][0][out_odd].data = 0;
+ _dcd.bdt[0][0][out_odd].own = 0;
_dcd.bdt[0][0][out_odd ^ 1].data = 1;
_dcd.bdt[0][1][in_odd].data = 1;
+ _dcd.bdt[0][1][in_odd].own = 0;
_dcd.bdt[0][1][in_odd ^ 1].data = 0;
+ _dcd.bdt[0][1][in_odd ^ 1].own = 0;
dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_OUT),
_dcd.setup_packet, sizeof(_dcd.setup_packet));
}
@@ -475,13 +489,12 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
intr_disable(rhport);
intr_clear(rhport);
-#if CFG_TUSB_MCU == OPT_MCU_PIC32MM
- TRISBbits.TRISB6 = 1;
-#endif
-
tu_memclr(&_dcd, sizeof(_dcd));
#if TU_PIC_INT_SIZE == 4
+ // The USBBUSY bit is present on PIC32s and we're required to check it
+ // prior to powering on the USB peripheral (see DS61126F page 27)
+ while (U1PWRCbits.USBBUSY);
U1PWRCSET = _U1PWRC_USBPWR_MASK;
#else
U1PWRCbits.USBPWR = 1;
@@ -505,6 +518,19 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
return true;
}
+bool dcd_deinit(uint8_t rhport)
+{
+ U1CON = 0;
+ U1IE = 0;
+ U1OTGIE = 0;
+#if TU_PIC_INT_SIZE == 4
+ U1PWRCCLR = _U1PWRC_USUSPEND_MASK | _U1PWRC_USBPWR_MASK;
+#else
+ U1PWRC &= ~(_U1PWRC_USUSPEND_MASK | _U1PWRC_USBPWR_MASK);
+#endif
+ return true;
+}
+
void dcd_int_enable(uint8_t rhport)
{
intr_enable(rhport);
@@ -529,8 +555,25 @@ void dcd_remote_wakeup(uint8_t rhport)
#else
U1CONbits.RESUME = 1;
#endif
- unsigned cnt = 25000000 / 1000;
+
+ // FIXME: Assert RESUME signal correctly, requires device-specific handling
+ // For now we use a hardcoded cycle-based delay which attempts to delay 10ms
+ // at the most common CPU frequencies. On PIC32s we assume the loop body
+ // takes 3 cycles. On 16-bit PICs we assume the XC16 compiler is in use and
+ // use its `__delay_ms' function.
+
+#if CFG_TUSB_MCU == OPT_MCU_PIC32MM
+ uint32_t cnt = 24000000 / 1000 / 3;
while (cnt--) asm volatile("nop");
+#elif CFG_TUSB_MCU == OPT_MCU_PIC32MX
+ uint32_t cnt = 40000000 / 1000 / 3;
+ while (cnt--) asm volatile("nop");
+#elif CFG_TUSB_MCU == OPT_MCU_PIC32MK
+ uint32_t cnt = 120000000 / 1000 / 3;
+ while (cnt--) asm volatile("nop");
+#else
+ __delay_ms(10);
+#endif
#if TU_PIC_INT_SIZE == 4
U1CONCLR = _U1CON_RESUME_MASK;
@@ -738,8 +781,11 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
//--------------------------------------------------------------------+
void dcd_int_handler(uint8_t rhport)
{
- uint32_t is = U1IR;
- uint32_t msk = U1IE;
+ uint32_t is, msk;
+
+ // Part 1 - "USB interrupts"
+ is = U1IR;
+ msk = U1IE;
U1IR = is & ~msk;
is &= msk;
@@ -747,7 +793,7 @@ void dcd_int_handler(uint8_t rhport)
if (is & _U1IR_UERRIF_MASK) {
uint32_t es = U1EIR;
U1EIR = es;
- U1IR = is; /* discard any pending events */
+ U1IR = is; /* discard any pending events */
}
if (is & _U1IR_URSTIF_MASK) {
@@ -758,29 +804,66 @@ void dcd_int_handler(uint8_t rhport)
if (is & _U1IR_IDLEIF_MASK) {
// Note Host usually has extra delay after bus reset (without SOF), which could falsely
// detected as Sleep event. Though usbd has debouncing logic so we are good
+
+ /*
+ * NOTE: Do not clear U1OTGIRbits.ACTVIF here!
+ * Reason:
+ * ACTVIF is only generated once an IDLEIF has been generated.
+ * This is a 1:1 ratio interrupt generation.
+ * For every IDLEIF, there will be only one ACTVIF regardless of
+ * the number of subsequent bus transitions.
+ *
+ * If the ACTIF is cleared here, a problem could occur when:
+ * [ IDLE ][bus activity ->
+ * <--- 3 ms -----> ^
+ * ^ ACTVIF=1
+ * IDLEIF=1
+ * # # # # (#=Program polling flags)
+ * ^
+ * This polling loop will see both
+ * IDLEIF=1 and ACTVIF=1.
+ * However, the program services IDLEIF first
+ * because ACTIVIE=0.
+ * If this routine clears the only ACTIVIF,
+ * then it can never get out of the suspend
+ * mode.
+ */
+ U1OTGIESET = _U1OTGIE_ACTVIE_MASK;
U1IR = _U1IR_IDLEIF_MASK;
process_bus_sleep(rhport);
}
- if (is & _U1IR_RESUMEIF_MASK) {
- U1IR = _U1IR_RESUMEIF_MASK;
- process_bus_resume(rhport);
- }
-
if (is & _U1IR_SOFIF_MASK) {
U1IR = _U1IR_SOFIF_MASK;
dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
}
if (is & _U1IR_STALLIF_MASK) {
- U1IR = _U1IR_STALLIF_MASK;
process_stall(rhport);
+ U1IR = _U1IR_STALLIF_MASK;
}
if (is & _U1IR_TRNIF_MASK) {
process_tokdne(rhport);
}
+ // Part 2 - "USB OTG interrupts"
+ is = U1OTGIR;
+ msk = U1OTGIE;
+
+ U1OTGIR = is & ~msk;
+ is &= msk;
+
+ if (is & _U1OTGIR_ACTVIF_MASK) {
+#if TU_PIC_INT_SIZE == 4
+ U1OTGIECLR = _U1OTGIE_ACTVIE_MASK;
+#else
+ U1OTGIE &= ~_U1OTGIE_ACTVIE_MASK;
+#endif
+ U1OTGIR = _U1OTGIR_ACTVIF_MASK;
+ process_bus_resume(rhport);
+ }
+
intr_clear(rhport);
}
diff --git a/src/portable/nxp/khci/hcd_khci.c b/src/portable/nxp/khci/hcd_khci.c
index 056dbf40b..c3c901c5d 100644
--- a/src/portable/nxp/khci/hcd_khci.c
+++ b/src/portable/nxp/khci/hcd_khci.c
@@ -541,6 +541,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
return true;
}
+bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) {
+ (void) rhport; (void) daddr; (void) ep_addr;
+ return false; // TODO not implemented yet
+}
+
/* The address of buffer must be aligned to 4 byte boundary. And it must be at least 4 bytes long.
* DMA writes data in 4 byte unit */
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen)
diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c
index 7d5cfb5b0..7c637ce0c 100644
--- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c
+++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c
@@ -297,7 +297,7 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
dcd_reg->EPLISTSTART = (uint32_t) _dcd.ep;
dcd_reg->DATABUFSTART = tu_align((uint32_t) &_dcd, TU_BIT(22)); // 22-bit alignment
- dcd_reg->INTSTAT |= dcd_reg->INTSTAT; // clear all pending interrupt
+ dcd_reg->INTSTAT = dcd_reg->INTSTAT; // clear all pending interrupt
dcd_reg->INTEN = INT_DEVICE_STATUS_MASK;
dcd_reg->DEVCMDSTAT |= DEVCMDSTAT_DEVICE_ENABLE_MASK | DEVCMDSTAT_DEVICE_CONNECT_MASK |
DEVCMDSTAT_RESET_CHANGE_MASK | DEVCMDSTAT_CONNECT_CHANGE_MASK | DEVCMDSTAT_SUSPEND_CHANGE_MASK;
@@ -563,7 +563,8 @@ void dcd_int_handler(uint8_t rhport)
uint32_t const cmd_stat = dcd_reg->DEVCMDSTAT;
- uint32_t int_status = dcd_reg->INTSTAT & dcd_reg->INTEN;
+ uint32_t int_status = dcd_reg->INTSTAT;
+ int_status &= dcd_reg->INTEN;
dcd_reg->INTSTAT = int_status; // Acknowledge handled interrupt
if (int_status == 0) return;
diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c
index ce35eab70..672ad0443 100644
--- a/src/portable/ohci/ohci.c
+++ b/src/portable/ohci/ohci.c
@@ -451,7 +451,6 @@ static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd)
//--------------------------------------------------------------------+
// Endpoint API
//--------------------------------------------------------------------+
-
bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc)
{
(void) rhport;
@@ -486,6 +485,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
return true;
}
+bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) {
+ (void) rhport; (void) daddr; (void) ep_addr;
+ return false; // TODO not implemented yet
+}
+
bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8])
{
(void) rhport;
diff --git a/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c b/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c
index 6422afff1..225a44dcf 100644
--- a/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c
+++ b/src/portable/raspberrypi/pio_usb/hcd_pio_usb.c
@@ -122,6 +122,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
return pio_usb_host_endpoint_open(pio_rhport, dev_addr, (uint8_t const *) desc_ep, need_pre);
}
+bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) {
+ uint8_t const pio_rhport = RHPORT_PIO(rhport);
+ return pio_usb_host_endpoint_close(pio_rhport, daddr, ep_addr);
+}
+
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) {
uint8_t const pio_rhport = RHPORT_PIO(rhport);
return pio_usb_host_endpoint_transfer(pio_rhport, dev_addr, ep_addr, buffer, buflen);
diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c
index af08b549d..358ce84bc 100644
--- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c
+++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c
@@ -148,6 +148,32 @@ static void hw_endpoint_xfer(uint8_t ep_addr, uint8_t* buffer, uint16_t total_by
hw_endpoint_xfer_start(ep, buffer, total_bytes);
}
+static void hw_endpoint_abort_xfer(struct hw_endpoint* ep) {
+ // Abort any pending transfer
+ // Due to Errata RP2040-E2: ABORT flag is only applicable for B2 and later (unusable for B0, B1).
+ // Which means we are not guaranteed to safely abort pending transfer on B0 and B1.
+ const uint8_t dir = tu_edpt_dir(ep->ep_addr);
+ const uint8_t epnum = tu_edpt_number(ep->ep_addr);
+ const uint32_t abort_mask = TU_BIT((epnum << 1) | (dir ? 0 : 1));
+ if (rp2040_chip_version() >= 2) {
+ usb_hw_set->abort = abort_mask;
+ while ((usb_hw->abort_done & abort_mask) != abort_mask) {}
+ }
+
+ uint32_t buf_ctrl = USB_BUF_CTRL_SEL; // reset to buffer 0
+ if (ep->next_pid) {
+ buf_ctrl |= USB_BUF_CTRL_DATA1_PID;
+ }
+
+ _hw_endpoint_buffer_control_set_value32(ep, buf_ctrl);
+ hw_endpoint_reset_transfer(ep);
+
+ if (rp2040_chip_version() >= 2) {
+ usb_hw_clear->abort_done = abort_mask;
+ usb_hw_clear->abort = abort_mask;
+ }
+}
+
static void __tusb_irq_path_func(hw_handle_buff_status)(void) {
uint32_t remaining_buffers = usb_hw->buf_status;
pico_trace("buf_status = 0x%08lx\r\n", remaining_buffers);
@@ -178,25 +204,10 @@ TU_ATTR_ALWAYS_INLINE static inline void reset_ep0(void) {
// setup transfer. Also clear a stall in case
for (uint8_t dir = 0; dir < 2; dir++) {
struct hw_endpoint* ep = hw_endpoint_get_by_num(0, dir);
- if (ep->active) {
- // Abort any pending transfer from a prior control transfer per USB specs
- // Due to Errata RP2040-E2: ABORT flag is only applicable for B2 and later (unusable for B0, B1).
- // Which means we are not guaranteed to safely abort pending transfer on B0 and B1.
- uint32_t const abort_mask = (dir ? USB_EP_ABORT_EP0_IN_BITS : USB_EP_ABORT_EP0_OUT_BITS);
- if (rp2040_chip_version() >= 2) {
- usb_hw_set->abort = abort_mask;
- while ((usb_hw->abort_done & abort_mask) != abort_mask) {}
- }
-
- _hw_endpoint_buffer_control_set_value32(ep, USB_BUF_CTRL_DATA1_PID | USB_BUF_CTRL_SEL);
- hw_endpoint_reset_transfer(ep);
-
- if (rp2040_chip_version() >= 2) {
- usb_hw_clear->abort_done = abort_mask;
- usb_hw_clear->abort = abort_mask;
- }
- }
ep->next_pid = 1u;
+ if (ep->active) {
+ hw_endpoint_abort_xfer(ep); // Abort any pending transfer per USB specs
+ }
}
}
@@ -495,12 +506,14 @@ bool dcd_edpt_iso_alloc(uint8_t rhport, uint8_t ep_addr, uint16_t largest_packet
// New API: Configure and enable an ISO endpoint according to descriptor
bool dcd_edpt_iso_activate(uint8_t rhport, tusb_desc_endpoint_t const * ep_desc) {
(void) rhport;
- const uint8_t ep_addr = ep_desc->bEndpointAddress;
- // Fill in endpoint control register with buffer offset
- struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_addr);
- TU_ASSERT(ep->hw_data_buf != NULL); // must be inited and buffer allocated
- ep->wMaxPacketSize = ep_desc->wMaxPacketSize;
+ struct hw_endpoint* ep = hw_endpoint_get_by_addr(ep_desc->bEndpointAddress);
+ TU_ASSERT(ep->hw_data_buf != NULL); // must be inited and allocated previously
+ if (ep->active) {
+ hw_endpoint_abort_xfer(ep); // abort any pending transfer
+ }
+
+ ep->wMaxPacketSize = ep_desc->wMaxPacketSize;
hw_endpoint_enable(ep);
return true;
}
diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c
index 2c0a3fd49..cd8c905d5 100644
--- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c
+++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c
@@ -459,28 +459,33 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport)
}
// Close all opened endpoint belong to this device
-void hcd_device_close(uint8_t rhport, uint8_t dev_addr)
-{
+void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
pico_trace("hcd_device_close %d\n", dev_addr);
(void) rhport;
- if (dev_addr == 0) return;
+ // reset epx if it is currently active with unplugged device
+ if (epx.configured && epx.active && epx.dev_addr == dev_addr) {
+ epx.configured = false;
+ *epx.endpoint_control = 0;
+ *epx.buffer_control = 0;
+ hw_endpoint_reset_transfer(&epx);
+ }
- for (size_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++)
- {
- hw_endpoint_t* ep = &ep_pool[i];
+ // dev0 only has ep0
+ if (dev_addr != 0) {
+ for (size_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++) {
+ hw_endpoint_t *ep = &ep_pool[i];
+ if (ep->dev_addr == dev_addr && ep->configured) {
+ // in case it is an interrupt endpoint, disable it
+ usb_hw_clear->int_ep_ctrl = (1 << (ep->interrupt_num + 1));
+ usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = 0;
- if (ep->dev_addr == dev_addr && ep->configured)
- {
- // in case it is an interrupt endpoint, disable it
- usb_hw_clear->int_ep_ctrl = (1 << (ep->interrupt_num + 1));
- usb_hw->int_ep_addr_ctrl[ep->interrupt_num] = 0;
-
- // unconfigure the endpoint
- ep->configured = false;
- *ep->endpoint_control = 0;
- *ep->buffer_control = 0;
- hw_endpoint_reset_transfer(ep);
+ // unconfigure the endpoint
+ ep->configured = false;
+ *ep->endpoint_control = 0;
+ *ep->buffer_control = 0;
+ hw_endpoint_reset_transfer(ep);
+ }
}
}
}
@@ -509,7 +514,6 @@ void hcd_int_disable(uint8_t rhport)
//--------------------------------------------------------------------+
// Endpoint API
//--------------------------------------------------------------------+
-
bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc)
{
(void) rhport;
@@ -530,6 +534,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
return true;
}
+bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) {
+ (void) rhport; (void) daddr; (void) ep_addr;
+ return false; // TODO not implemented yet
+}
+
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen)
{
(void) rhport;
@@ -557,7 +566,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
}
// If a normal transfer (non-interrupt) then initiate using
- // sie ctrl registers. Otherwise interrupt ep registers should
+ // sie ctrl registers. Otherwise, interrupt ep registers should
// already be configured
if ( ep == &epx )
{
@@ -597,13 +606,12 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet
(void) rhport;
// Copy data into setup packet buffer
- for ( uint8_t i = 0; i < 8; i++ )
- {
+ for (uint8_t i = 0; i < 8; i++) {
usbh_dpram->setup_packet[i] = setup_packet[i];
}
// Configure EP0 struct with setup info for the trans complete
- struct hw_endpoint * ep = _hw_endpoint_allocate(0);
+ struct hw_endpoint * ep = _hw_endpoint_allocate( (uint8_t) TUSB_XFER_CONTROL);
TU_ASSERT(ep);
// EPX should be inactive
diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c
index 43f48da39..9d0bd762d 100644
--- a/src/portable/raspberrypi/rp2040/rp2040_usb.c
+++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c
@@ -110,7 +110,7 @@ void __tusb_irq_path_func(_hw_endpoint_buffer_control_update32)(struct hw_endpoi
*ep->buffer_control = value & ~USB_BUF_CTRL_AVAIL;
// 4.1.2.5.1 Con-current access: 12 cycles (should be good for 48*12Mhz = 576Mhz) after write to buffer control
// Don't need delay in host mode as host is in charge
- if ( !is_host_mode()) {
+ if (!is_host_mode()) {
busy_wait_at_least_cycles(12);
}
}
diff --git a/src/portable/renesas/rusb2/hcd_rusb2.c b/src/portable/renesas/rusb2/hcd_rusb2.c
index 4c81b05be..3e4b36981 100644
--- a/src/portable/renesas/rusb2/hcd_rusb2.c
+++ b/src/portable/renesas/rusb2/hcd_rusb2.c
@@ -718,6 +718,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const
return true;
}
+bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) {
+ (void) rhport; (void) daddr; (void) ep_addr;
+ return false; // TODO not implemented yet
+}
+
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen)
{
bool r;
diff --git a/src/portable/synopsys/dwc2/hcd_dwc2.c b/src/portable/synopsys/dwc2/hcd_dwc2.c
index ebbb6200a..7cbef05b7 100644
--- a/src/portable/synopsys/dwc2/hcd_dwc2.c
+++ b/src/portable/synopsys/dwc2/hcd_dwc2.c
@@ -26,7 +26,7 @@
#include "tusb_option.h"
-#if CFG_TUH_ENABLED && defined(TUP_USBIP_DWC2)
+#if CFG_TUH_ENABLED && defined(TUP_USBIP_DWC2) && !CFG_TUH_MAX3421
#if !(CFG_TUH_DWC2_SLAVE_ENABLE || CFG_TUH_DWC2_DMA_ENABLE)
#error DWC2 require either CFG_TUH_DWC2_SLAVE_ENABLE or CFG_TUH_DWC2_DMA_ENABLE to be enabled
@@ -506,6 +506,11 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_endpoint_t*
return true;
}
+bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) {
+ (void) rhport; (void) daddr; (void) ep_addr;
+ return false; // TODO not implemented yet
+}
+
// clean up channel after part of transfer is done but the whole urb is not complete
static void channel_xfer_out_wrapup(dwc2_regs_t* dwc2, uint8_t ch_id) {
hcd_xfer_t* xfer = &_hcd_data.xfer[ch_id];
@@ -1177,6 +1182,7 @@ static void handle_channel_irq(uint8_t rhport, bool in_isr) {
static bool handle_sof_irq(uint8_t rhport, bool in_isr) {
(void) in_isr;
dwc2_regs_t* dwc2 = DWC2_REG(rhport);
+ dwc2->gintsts = GINTSTS_SOF; // Clear the SOF interrupt flag
bool more_isr = false;
diff --git a/src/portable/template/hcd_template.c b/src/portable/template/hcd_template.c
index d8bca196f..1202c4ef4 100644
--- a/src/portable/template/hcd_template.c
+++ b/src/portable/template/hcd_template.c
@@ -36,24 +36,19 @@
// optional hcd configuration, called by tuh_configure()
bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) {
- (void) rhport;
- (void) cfg_id;
- (void) cfg_param;
-
+ (void) rhport; (void) cfg_id; (void) cfg_param;
return false;
}
// Initialize controller to host mode
bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
- (void) rhport;
- (void) rh_init;
+ (void) rhport; (void) rh_init;
return false;
}
// Interrupt Handler
void hcd_int_handler(uint8_t rhport, bool in_isr) {
- (void) rhport;
- (void) in_isr;
+ (void) rhport; (void) in_isr;
}
// Enable USB interrupt
@@ -69,7 +64,6 @@ void hcd_int_disable(uint8_t rhport) {
// Get frame number (1ms)
uint32_t hcd_frame_number(uint8_t rhport) {
(void) rhport;
-
return 0;
}
@@ -80,7 +74,6 @@ uint32_t hcd_frame_number(uint8_t rhport) {
// Get the current connect status of roothub port
bool hcd_port_connect_status(uint8_t rhport) {
(void) rhport;
-
return false;
}
@@ -98,14 +91,12 @@ void hcd_port_reset_end(uint8_t rhport) {
// Get port link speed
tusb_speed_t hcd_port_speed_get(uint8_t rhport) {
(void) rhport;
-
return TUSB_SPEED_FULL;
}
// HCD closes all opened endpoints belong to this device
void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
- (void) rhport;
- (void) dev_addr;
+ (void) rhport; (void) dev_addr;
}
//--------------------------------------------------------------------+
@@ -114,49 +105,37 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
// Open an endpoint
bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) {
- (void) rhport;
- (void) dev_addr;
- (void) ep_desc;
-
+ (void) rhport; (void) dev_addr; (void) ep_desc;
return false;
}
+bool hcd_edpt_close(uint8_t rhport, uint8_t daddr, uint8_t ep_addr) {
+ (void) rhport; (void) daddr; (void) ep_addr;
+ return false; // TODO not implemented yet
+}
+
// Submit a transfer, when complete hcd_event_xfer_complete() must be invoked
bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) {
- (void) rhport;
- (void) dev_addr;
- (void) ep_addr;
- (void) buffer;
- (void) buflen;
-
+ (void) rhport; (void) dev_addr; (void) ep_addr; (void) buffer; (void) buflen;
return false;
}
// Abort a queued transfer. Note: it can only abort transfer that has not been started
// Return true if a queued transfer is aborted, false if there is no transfer to abort
bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
- (void) rhport;
- (void) dev_addr;
- (void) ep_addr;
-
+ (void) rhport; (void) dev_addr; (void) ep_addr;
return false;
}
// Submit a special transfer to send 8-byte Setup Packet, when complete hcd_event_xfer_complete() must be invoked
bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) {
- (void) rhport;
- (void) dev_addr;
- (void) setup_packet;
-
+ (void) rhport; (void) dev_addr; (void) setup_packet;
return false;
}
// clear stall, data toggle is also reset to DATA0
bool hcd_edpt_clear_stall(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
- (void) rhport;
- (void) dev_addr;
- (void) ep_addr;
-
+ (void) rhport; (void) dev_addr; (void) ep_addr;
return false;
}
diff --git a/src/portable/wch/dcd_ch32_usbfs.c b/src/portable/wch/dcd_ch32_usbfs.c
index 4e8e25a00..c248ba14e 100644
--- a/src/portable/wch/dcd_ch32_usbfs.c
+++ b/src/portable/wch/dcd_ch32_usbfs.c
@@ -192,7 +192,8 @@ void dcd_int_handler(uint8_t rhport) {
data.xfer[0][TUSB_DIR_OUT].max_size = 64;
data.xfer[0][TUSB_DIR_IN].max_size = 64;
- dcd_event_bus_signal(rhport, DCD_EVENT_BUS_RESET, true);
+ //dcd_event_bus_reset(rhport, (USBOTG_FS->BASE_CTRL & USBFS_CTRL_LOW_SPEED) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL, true);
+ dcd_event_bus_reset(rhport, (USBOTG_FS->UDEV_CTRL & USBFS_UDEV_CTRL_LOW_SPEED) ? TUSB_SPEED_LOW : TUSB_SPEED_FULL, true);
USBOTG_FS->DEV_ADDR = 0x00;
EP_RX_CTRL(0) = USBFS_EP_R_RES_ACK;
diff --git a/src/tinyusb.mk b/src/tinyusb.mk
index 89ea0212c..a9f623c24 100644
--- a/src/tinyusb.mk
+++ b/src/tinyusb.mk
@@ -21,6 +21,7 @@ TINYUSB_SRC_C += \
src/host/hub.c \
src/class/cdc/cdc_host.c \
src/class/hid/hid_host.c \
+ src/class/midi/midi_host.c \
src/class/msc/msc_host.c \
src/class/vendor/vendor_host.c \
src/typec/usbc.c \
diff --git a/src/tusb.c b/src/tusb.c
index 85ab1d6ae..13b89997c 100644
--- a/src/tusb.c
+++ b/src/tusb.c
@@ -142,7 +142,9 @@ void tusb_int_handler(uint8_t rhport, bool in_isr) {
uint8_t const* tu_desc_find(uint8_t const* desc, uint8_t const* end, uint8_t byte1) {
while (desc + 1 < end) {
- if (desc[1] == byte1) return desc;
+ if (desc[1] == byte1) {
+ return desc;
+ }
desc += desc[DESC_OFFSET_LEN];
}
return NULL;
@@ -150,7 +152,9 @@ uint8_t const* tu_desc_find(uint8_t const* desc, uint8_t const* end, uint8_t byt
uint8_t const* tu_desc_find2(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2) {
while (desc + 2 < end) {
- if (desc[1] == byte1 && desc[2] == byte2) return desc;
+ if (desc[1] == byte1 && desc[2] == byte2) {
+ return desc;
+ }
desc += desc[DESC_OFFSET_LEN];
}
return NULL;
@@ -158,7 +162,9 @@ uint8_t const* tu_desc_find2(uint8_t const* desc, uint8_t const* end, uint8_t by
uint8_t const* tu_desc_find3(uint8_t const* desc, uint8_t const* end, uint8_t byte1, uint8_t byte2, uint8_t byte3) {
while (desc + 3 < end) {
- if (desc[1] == byte1 && desc[2] == byte2 && desc[3] == byte3) return desc;
+ if (desc[1] == byte1 && desc[2] == byte2 && desc[3] == byte3) {
+ return desc;
+ }
desc += desc[DESC_OFFSET_LEN];
}
return NULL;
@@ -199,7 +205,7 @@ bool tu_edpt_release(tu_edpt_state_t* ep_state, osal_mutex_t mutex) {
return ret;
}
-bool tu_edpt_validate(tusb_desc_endpoint_t const* desc_ep, tusb_speed_t speed) {
+bool tu_edpt_validate(tusb_desc_endpoint_t const* desc_ep, tusb_speed_t speed, bool is_host) {
uint16_t const max_packet_size = tu_edpt_packet_size(desc_ep);
TU_LOG2(" Open EP %02X with Size = %u\r\n", desc_ep->bEndpointAddress, max_packet_size);
@@ -215,8 +221,17 @@ bool tu_edpt_validate(tusb_desc_endpoint_t const* desc_ep, tusb_speed_t speed) {
// Bulk highspeed must be EXACTLY 512
TU_ASSERT(max_packet_size == 512);
} else {
- // TODO Bulk fullspeed can only be 8, 16, 32, 64
- TU_ASSERT(max_packet_size <= 64);
+ // Bulk fullspeed can only be 8, 16, 32, 64
+ if (is_host && max_packet_size == 512) {
+ // HACK: while in host mode, some device incorrectly always report 512 regardless of link speed
+ // overwrite descriptor to force 64
+ TU_LOG1(" WARN: EP max packet size is 512 in fullspeed, force to 64\r\n");
+ tusb_desc_endpoint_t* hacked_ep = (tusb_desc_endpoint_t*) (uintptr_t) desc_ep;
+ hacked_ep->wMaxPacketSize = tu_htole16(64);
+ } else {
+ TU_ASSERT(max_packet_size == 8 || max_packet_size == 16 ||
+ max_packet_size == 32 || max_packet_size == 64);
+ }
}
break;
diff --git a/src/tusb.h b/src/tusb.h
index cb6021b33..dfba21ddf 100644
--- a/src/tusb.h
+++ b/src/tusb.h
@@ -59,6 +59,10 @@
#include "class/cdc/cdc_host.h"
#endif
+ #if CFG_TUH_MIDI
+ #include "class/midi/midi_host.h"
+ #endif
+
#if CFG_TUH_VENDOR
#include "class/vendor/vendor_host.h"
#endif
diff --git a/test/hil/hil_test.py b/test/hil/hil_test.py
index a9f5dc1e1..8b89de66c 100755
--- a/test/hil/hil_test.py
+++ b/test/hil/hil_test.py
@@ -81,7 +81,7 @@ def get_serial_dev(id, vendor_str, product_str, ifnum):
return f'/dev/serial/by-id/usb-{vendor_str}_{product_str}_{id}-if{ifnum:02d}'
else:
# just use id: mostly for cp210x/ftdi flasher
- pattern = f'/dev/serial/by-id/usb-*_{id}-if{ifnum:02d}*'
+ pattern = f'/dev/serial/by-id/usb-*_{id}-if*'
port_list = glob.glob(pattern)
return port_list[0]
@@ -98,20 +98,18 @@ def get_hid_dev(id, vendor_str, product_str, event):
def open_serial_dev(port):
timeout = ENUM_TIMEOUT
ser = None
- while timeout:
+ while timeout > 0:
if os.path.exists(port):
try:
- # slight delay since kernel may occupy the port briefly
- time.sleep(0.5)
- timeout = timeout - 0.5
ser = serial.Serial(port, baudrate=115200, timeout=5)
break
except serial.SerialException:
+ print(f'serial {port} not reaady {timeout} sec')
pass
- time.sleep(0.5)
- timeout = timeout - 0.5
+ time.sleep(0.1)
+ timeout -= 0.1
- assert timeout, f'Cannot open port f{port}' if os.path.exists(port) else f'Port {port} not existed'
+ assert timeout > 0, f'Cannot open port f{port}' if os.path.exists(port) else f'Port {port} not existed'
return ser
@@ -119,7 +117,7 @@ def read_disk_file(uid, lun, fname):
# open_fs("fat://{dev}) require 'pip install pyfatfs'
dev = get_disk_dev(uid, 'TinyUSB', lun)
timeout = ENUM_TIMEOUT
- while timeout:
+ while timeout > 0:
if os.path.exists(dev):
fat = fs.open_fs(f'fat://{dev}?read_only=true')
try:
@@ -132,7 +130,7 @@ def read_disk_file(uid, lun, fname):
time.sleep(1)
timeout -= 1
- assert timeout, f'Storage {dev} not existed'
+ assert timeout > 0, f'Storage {dev} not existed'
return None
@@ -202,14 +200,14 @@ def reset_stflash(board):
def flash_openocd(board, firmware):
flasher = board['flasher']
ret = run_cmd(f'openocd -c "tcl_port disabled" -c "gdb_port disabled" -c "adapter serial {flasher["uid"]}" '
- f'{flasher["args"]} -c init -c halt -c "program {firmware}.elf verify" -c reset -c exit')
+ f'{flasher["args"]} -c "init; halt; program {firmware}.elf verify; reset; exit"')
return ret
def reset_openocd(board):
flasher = board['flasher']
ret = run_cmd(f'openocd -c "tcl_port disabled" -c "gdb_port disabled" -c "adapter serial {flasher["uid"]}" '
- f'{flasher["args"]} -c "reset exit"')
+ f'{flasher["args"]} -c "init; reset run; exit"')
return ret
@@ -304,11 +302,11 @@ def test_dual_host_info_to_device_cdc(board):
ser = open_serial_dev(port)
# read from cdc, first line should contain vid/pid and serial
- data = ser.read(1000)
+ data = ser.read(10000)
ser.close()
if len(data) == 0:
assert False, 'No data from device'
- lines = data.decode('utf-8').splitlines()
+ lines = data.decode('utf-8', errors='ignore').splitlines()
enum_dev_sn = []
for l in lines:
@@ -319,6 +317,7 @@ def test_dual_host_info_to_device_cdc(board):
if set(declared_devs) != set(enum_dev_sn):
failed_msg = f'Expected {declared_devs}, Enumerated {enum_dev_sn}'
+ print('\n'.join(lines))
assert False, failed_msg
return 0
@@ -337,12 +336,12 @@ def test_host_device_info(board):
ret = globals()[f'reset_{flasher["name"].lower()}'](board)
assert ret.returncode == 0, 'Failed to reset device'
- data = ser.read(1000)
+ data = ser.read(10000)
ser.close()
if len(data) == 0:
assert False, 'No data from device'
+ lines = data.decode('utf-8', errors='ignore').splitlines()
- lines = data.decode('utf-8').splitlines()
enum_dev_sn = []
for l in lines:
vid_pid_sn = re.search(r'ID ([0-9a-fA-F]+):([0-9a-fA-F]+) SN (\w+)', l)
@@ -352,8 +351,8 @@ def test_host_device_info(board):
if set(declared_devs) != set(enum_dev_sn):
failed_msg = f'Expected {declared_devs}, Enumerated {enum_dev_sn}'
+ print('\n'.join(lines))
assert False, failed_msg
-
return 0
@@ -419,7 +418,7 @@ def test_device_dfu(board):
# Wait device enum
timeout = ENUM_TIMEOUT
- while timeout:
+ while timeout > 0:
ret = run_cmd(f'dfu-util -l')
stdout = ret.stdout.decode()
if f'serial="{uid}"' in stdout and 'Found DFU: [cafe:4000]' in stdout:
@@ -427,7 +426,7 @@ def test_device_dfu(board):
time.sleep(1)
timeout = timeout - 1
- assert timeout, 'Device not available'
+ assert timeout > 0, 'Device not available'
f_dfu0 = f'dfu0_{uid}'
f_dfu1 = f'dfu1_{uid}'
@@ -460,7 +459,7 @@ def test_device_dfu_runtime(board):
# Wait device enum
timeout = ENUM_TIMEOUT
- while timeout:
+ while timeout > 0:
ret = run_cmd(f'dfu-util -l')
stdout = ret.stdout.decode()
if f'serial="{uid}"' in stdout and 'Found Runtime: [cafe:4000]' in stdout:
@@ -468,7 +467,7 @@ def test_device_dfu_runtime(board):
time.sleep(1)
timeout = timeout - 1
- assert timeout, 'Device not available'
+ assert timeout > 0, 'Device not available'
def test_device_hid_boot_interface(board):
@@ -478,13 +477,13 @@ def test_device_hid_boot_interface(board):
mouse2 = get_hid_dev(uid, 'TinyUSB', 'TinyUSB_Device', 'if01-mouse')
# Wait device enum
timeout = ENUM_TIMEOUT
- while timeout:
+ while timeout > 0:
if os.path.exists(kbd) and os.path.exists(mouse1) and os.path.exists(mouse2):
break
time.sleep(1)
timeout = timeout - 1
- assert timeout, 'HID device not available'
+ assert timeout > 0, 'HID device not available'
def test_device_hid_composite_freertos(id):
@@ -561,6 +560,9 @@ def test_board(board):
print('Skip (no binary)')
continue
+ if verbose:
+ print(f'Flashing {fw_name}.elf')
+
# flash firmware. It may fail randomly, retry a few times
max_rety = 2
for i in range(max_rety):
@@ -577,10 +579,10 @@ def test_board(board):
print(f' {e}')
else:
print()
- print(f' Test failed: {e}, retry {i+1}')
+ print(f' Test failed: {e}, retry {i+2}/{max_rety}')
time.sleep(1)
else:
- print(f'Flashing failed, retry {i+1}')
+ print(f'Flashing failed, retry {i+2}/{max_rety}')
time.sleep(1)
if ret.returncode != 0:
diff --git a/test/hil/tinyusb.json b/test/hil/tinyusb.json
index 7393226eb..a9460bf9d 100644
--- a/test/hil/tinyusb.json
+++ b/test/hil/tinyusb.json
@@ -60,7 +60,7 @@
"name": "metro_m4_express",
"uid": "9995AD485337433231202020FF100A34",
"tests": {
- "device": true, "host": false, "dual": false,
+ "device": true, "host": false, "dual": true,
"dev_attached": [{"vid_pid": "1a86_55d4", "serial": "52D2002130"}]
},
"flasher": {
@@ -69,6 +69,19 @@
"args": "-device ATSAMD51J19"
}
},
+ {
+ "name": "mimxrt1064_evk",
+ "uid": "BAE96FB95AFA6DBB8F00005002001200",
+ "tests": {
+ "device": true, "host": true, "dual": true,
+ "dev_attached": [{"vid_pid": "1a86_55d4", "serial": "52D2023299"}]
+ },
+ "flasher": {
+ "name": "jlink",
+ "uid": "000725299165",
+ "args": "-device MIMXRT1064xxx6A"
+ }
+ },
{
"name": "lpcxpresso11u37",
"uid": "17121919",
@@ -98,8 +111,11 @@
{
"name": "raspberry_pi_pico",
"uid": "E6614C311B764A37",
+ "build" : {
+ "flags_on": ["CFG_TUH_RPI_PIO_USB"]
+ },
"tests": {
- "device": true, "host": false, "dual": false,
+ "device": true, "host": true, "dual": true,
"dev_attached": [{"vid_pid": "1a86_55d4", "serial": "52D2002470"}]
},
"flasher": {
@@ -111,8 +127,11 @@
{
"name": "raspberry_pi_pico2",
"uid": "560AE75E1C7152C9",
+ "build" : {
+ "flags_on": ["CFG_TUH_RPI_PIO_USB"]
+ },
"tests": {
- "device": true, "host": false, "dual": false,
+ "device": true, "host": true, "dual": true,
"dev_attached": [{"vid_pid": "1a86_55d4", "serial": "533D004242"}]
},
"flasher": {
@@ -157,9 +176,9 @@
"device": true, "host": false, "dual": false
},
"flasher": {
- "name": "stlink",
+ "name": "openocd",
"uid": "004C00343137510F39383538",
- "args": ""
+ "args": "-f interface/stlink.cfg -f target/stm32h7x.cfg"
}
},
{
diff --git a/tools/gen_presets.py b/tools/gen_presets.py
new file mode 100755
index 000000000..94b8d16b0
--- /dev/null
+++ b/tools/gen_presets.py
@@ -0,0 +1,105 @@
+#!/usr/bin/env python3
+import os
+import json
+from pathlib import Path
+
+def main():
+ board_list = []
+
+ # Find all board.cmake files
+ for root, dirs, files in os.walk("hw/bsp"):
+ for file in files:
+ if file == "board.cmake":
+ board_list.append(os.path.basename(root))
+
+ print('Generating presets for the following boards:')
+ print(board_list)
+
+ # Generate the presets
+ presets = {}
+ presets['version'] = 6
+
+ # Configure presets
+ presets['configurePresets'] = [
+ {"name": "default",
+ "hidden": True,
+ "description": r"Configure preset for the ${presetName} board",
+ "generator": "Ninja Multi-Config",
+ "binaryDir": r"${sourceDir}/build/${presetName}",
+ "cacheVariables": {
+ "CMAKE_DEFAULT_BUILD_TYPE": "RelWithDebInfo",
+ "BOARD": r"${presetName}"
+ }}]
+
+ presets['configurePresets'].extend(
+ sorted(
+ [
+ {
+ 'name': board,
+ 'inherits': 'default'
+ }
+ for board in board_list
+ ], key=lambda x: x['name']
+ )
+ )
+
+ # Build presets
+ # no inheritance since 'name' doesn't support macro expansion
+ presets['buildPresets'] = sorted(
+ [
+ {
+ 'name': board,
+ 'description': "Build preset for the " + board + " board",
+ 'configurePreset': board
+ }
+ for board in board_list
+ ], key=lambda x: x['name']
+ )
+
+ # Workflow presets
+ presets['workflowPresets'] = sorted(
+ [
+ {
+ "name": board,
+ "steps": [
+ {
+ "type": "configure",
+ "name": board
+ },
+ {
+ "type": "build",
+ "name": board
+ }
+ ]
+ }
+ for board in board_list
+ ], key=lambda x: x['name']
+ )
+
+ path_boardpresets = "hw/bsp/BoardPresets.json"
+ with open(path_boardpresets, "w") as f:
+ f.write('{}\n'.format(json.dumps(presets, indent=2)))
+
+ # Generate presets for examples
+ presets = {
+ "version": 6,
+ "include": [
+ ]
+ }
+
+ example_list = []
+ for root, dirs, files in os.walk("examples"):
+ for file in files:
+ # Filter out ESP-IDF CMakeLists.txt in src folder
+ if file == "CMakeLists.txt" and os.path.basename(root) != 'src':
+ presets['include'] = [os.path.relpath(path_boardpresets, root).replace(os.sep, '/')]
+ with open(os.path.join(root, 'CMakePresets.json'), 'w') as f:
+ f.write('{}\n'.format(json.dumps(presets, indent=2)))
+ example_list.append(os.path.basename(root))
+
+ print('Generating presets for the following examples:')
+ print(example_list)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/tools/get_deps.py b/tools/get_deps.py
index c8459c1f1..ba9dc23ce 100755
--- a/tools/get_deps.py
+++ b/tools/get_deps.py
@@ -58,8 +58,8 @@ deps_optional = {
'hw/mcu/nxp/mcux-sdk': ['https://github.com/hathach/mcux-sdk.git',
'144f1eb7ea8c06512e12f12b27383601c0272410',
'kinetis_k kinetis_k32l2 kinetis_kl lpc51 lpc54 lpc55 mcx imxrt'],
- 'hw/mcu/raspberry_pi/Pico-PIO-USB': ['https://github.com/sekigon-gonnoc/Pico-PIO-USB.git',
- 'fe9133fc513b82cc3dc62c67cb51f2339cf29ef7',
+ 'hw/mcu/raspberry_pi/Pico-PIO-USB': ['https://github.com/hathach/Pico-PIO-USB.git',
+ '810653f66adadba3e0e4b4b56d5167ac4f7fdbf7',
'rp2040'],
'hw/mcu/renesas/fsp': ['https://github.com/renesas/fsp.git',
'edcc97d684b6f716728a60d7a6fea049d9870bd6',
@@ -217,7 +217,12 @@ TOP = Path(__file__).parent.parent.resolve()
def run_cmd(cmd):
- return subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ r = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+ title = f'Command Error: {cmd}'
+ if r.returncode != 0:
+ print(title)
+ print(r.stdout.decode("utf-8"))
+ return r
def get_a_dep(d):