Просмотр исходного кода

Merge branch 'master' into add_hcd_for_msp_exp432e401y

Ha Thach 4 лет назад
Родитель
Сommit
6ecd93eb60

+ 2 - 1
.github/workflows/build_esp.yml

@@ -18,7 +18,8 @@ jobs:
         # ESP32-S2
         - 'espressif_saola_1'
         # ESP32-S3
-        - 'espressif_addax_1'
+        #- 'espressif_addax_1'
+        # S3 compile error with "dangerous relocation: call8: call target out of range: memcpy"
 
     steps:
     - name: Setup Python

+ 6 - 4
README.rst

@@ -32,8 +32,10 @@ Supported MCUs
 
 The stack supports the following MCUs:
 
+- **Broadcom:** BCM2837, BCM2711
 - **Dialog:** DA1469x
 - **Espressif:** ESP32-S2, ESP32-S3
+- **GigaDevice:** GD32VF103
 - **Infineon:** XMC4500
 - **MicroChip:** SAMD11, SAMD21, SAMD51, SAME5x, SAMG55, SAML21, SAML22, SAME7x
 - **NordicSemi:** nRF52833, nRF52840, nRF5340
@@ -41,15 +43,15 @@ The stack supports the following MCUs:
 - **NXP:**
 
   - iMX RT Series: RT1011, RT1015, RT1021, RT1052, RT1062, RT1064
-  - Kinetis: KL25, K32L2Bxx
+  - Kinetis: KL25, K32L2
   - LPC Series: 11u, 13, 15, 17, 18, 40, 43, 51u, 54, 55
 
 - **Raspberry Pi:** RP2040
-- **Renesas:** RX63N, RX65N
+- **Renesas:** RX63N, RX65N, RX72N
 - **Silabs:** EFM32GG
 - **Sony:** CXD56
-- **ST:** STM32 series: L0, L1, L4, L4+, F0, F1, F2, F3, F4, F7, H7
-- **TI:** MSP430
+- **ST:** STM32 series: F0, F1, F2, F3, F4, F7, H7, L0, L1, L4, L4+
+- **TI:** MSP430, MSP432E4, TM4C123
 - **ValentyUSB:** eptri
 
 Here is the list of `Supported Devices`_ that can be used with provided examples.

+ 0 - 1
docs/conf.py

@@ -21,7 +21,6 @@ extensions = [
     'sphinx.ext.intersphinx',
     'sphinx.ext.todo',
     'sphinx_autodoc_typehints',
-    'sphinxemoji.sphinxemoji',
 ]
 
 templates_path = ['_templates']

+ 116 - 115
docs/reference/supported.rst

@@ -2,126 +2,114 @@
 Supported Devices
 *****************
 
-
 Supported MCUs
 ==============
 
-.. admonition:: Warning
-   :class: warning
-
-   This table is a WIP! the data is not correct, tho if a device is listed, it likely works as a usb full speed device at the least.
-
-+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-| Manufacturer | Family             | Device            | Host               | FS                | HS                | Known Issues |
-+==============+====================+===================+====================+===================+===================+==============+
-| Dialog       | DA1469x            | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-| Espressif    | ESP32-S2           | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              | ESP32-S3           | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-| MicroChip    | SAMD11             | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              | SAMD21             | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              | SAMD51             | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              | SAME5x             | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              | SAMG55             | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              | SAML21             | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              | SAML22             | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              | SAME70,S70,V70,V71 | |:green_square:|  | |:red_square:|     | |:green_square:|  | |:green_square:|  |              |
-+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-| NordicSemi   | nRF52833           | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              | nRF52840           | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-| Nuvoton      | NUC120             | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              | NUC121/NUC125      | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              | NUC126             | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              | NUC505             | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-+--------------+-------+------------+-------------------+--------------------+-------------------+-------------------+--------------+
-| NXP          | iMX   | RT1011     | |:green_square:|  | |:yellow_square:|  | |:green_square:|  | |:x:|             |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | RT1015     | |:green_square:|  | |:yellow_square:|  | |:green_square:|  | |:x:|             |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | RT1021     | |:green_square:|  | |:yellow_square:|  | |:green_square:|  | |:x:|             |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | RT1052     | |:green_square:|  | |:yellow_square:|  | |:green_square:|  | |:x:|             |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | RT1062     | |:green_square:|  | |:yellow_square:|  | |:green_square:|  | |:x:|             |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | RT1064     | |:green_square:|  | |:yellow_square:|  | |:green_square:|  | |:x:|             |              |
-|              +-------+------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              | Kinetis KL25       | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              +-------+------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              | LPC   | 11u        | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | 13         | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | 15         | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | 17         | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | 18         |                   | |:yellow_square:|  | |:green_square:|  | |:x:|             |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | 40         |                   | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | 43         | |:green_square:|  | |:yellow_square:|  | |:green_square:|  | |:x:|             |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | 51u        | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | 54         | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | 55         | |:green_square:|  | |:x:|              | |:green_square:|  |                   |              |
-+--------------+-------+------------+-------------------+--------------------+-------------------+-------------------+--------------+
-| Raspberry Pi | RP2040             | |:green_square:|  | |:x:|              | |:green_square:|  |                   |              |
-+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-| Renesas      | RX63N              | |:green_square:|  |                    | |:green_square:|  | |:x:|             |              |
-|              +--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              | RX65N              | |:green_square:|  |                    | |:green_square:|  | |:x:|             |              |
-+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-| Silabs       | EFM32GG12          | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-| Sony         | CXD56              | |:green_square:|  | |:x:|              | |:green_square:|  | |:x:|             |              |
-+--------------+-------+------------+-------------------+--------------------+-------------------+-------------------+--------------+
-| ST           | STM32 | L0         | |:green_square:|  |                    | |:green_square:|  |                   |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | F0         | |:green_square:|  |                    | |:green_square:|  |                   |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | F1         | |:green_square:|  |                    | |:green_square:|  |                   |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | F2         | |:green_square:|  |                    | |:green_square:|  |                   |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | F3         | |:green_square:|  |                    | |:green_square:|  |                   |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | F4         | |:green_square:|  |                    | |:green_square:|  |                   |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | F7         | |:green_square:|  |                    | |:green_square:|  |                   |              |
-|              |       +------------+-------------------+--------------------+-------------------+-------------------+--------------+
-|              |       | H7         | |:green_square:|  |                    | |:green_square:|  | |:green_square:|  |              |
-+--------------+-------+------------+-------------------+--------------------+-------------------+-------------------+--------------+
-| TI           | MSP430             | |:green_square:|  |                    | |:green_square:|  |                   |              |
-+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
-| ValentyUSB   | eptri              | |:green_square:|  |                    | |:green_square:|  |                   |              |
-+--------------+--------------------+-------------------+--------------------+-------------------+-------------------+--------------+
++--------------+-----------------------+--------+------+-----------+-------------------+--------------+
+| Manufacturer | Family                | Device | Host | Highspeed | Driver            | Note         |
++==============+=======================+========+======+===========+===================+==============+
+| Broadcom     | BCM2711, BCM2837      | ✔      |      | ✔         | dwc2              |              |
++--------------+-----------------------+--------+------+-----------+-------------------+--------------+
+| Dialog       | DA1469x               | ✔      | ✖    | ✖         | da146xx           |              |
++--------------+-----------------------+--------+------+-----------+-------------------+--------------+
+| Espressif    | ESP32 S2, S3          | ✔      |      | ✖         | dwc2 or esp32sx   |              |
++--------------+-----------------------+--------+------+-----------+-------------------+--------------+
+| GigaDevice   | GD32VF103             | ✔      |      | ✖         | dwc2              |              |
++--------------+-----------------------+--------+------+-----------+-------------------+--------------+
+| Infineon     | XMC4500               | ✔      |      | ✖         | dwc2              |              |
++--------------+-----------------------+--------+------+-----------+-------------------+--------------+
+| MicroChip    | SAM D11, D21          | ✔      |      | ✖         | samd              |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | SAM D51, E5x          | ✔      |      | ✖         | samd              |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | SAM G55               | ✔      |      | ✖         | samg              |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | SAM L21, L22          | ✔      |      | ✖         | samd              |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | SAM E70,S70,V70,V71   | ✔      |      | ✔         | samx7x            |              |
++--------------+-----------------------+--------+------+-----------+-------------------+--------------+
+| NordicSemi   | nRF52833, nRF52840    | ✔      | ✖    | ✖         | nrf5x             |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | nRF5340               | ✔      | ✖    | ✖         | nrf5x             |              |
++--------------+-----------------------+--------+------+-----------+-------------------+--------------+
+| Nuvoton      | NUC120                | ✔      | ✖    | ✖         |                   |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | NUC121/NUC125         | ✔      | ✖    | ✖         |                   |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | NUC126                | ✔      | ✖    | ✖         |                   |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | NUC505                | ✔      |      | ✔         |                   |              |
++--------------+---------+-------------+--------+------+-----------+-------------------+--------------+
+| NXP          | iMXRT   | RT10xx      | ✔      | ✔    | ✔         | ci_hs             |              |
+|              +---------+-------------+--------+------+-----------+-------------------+--------------+
+|              | Kinetis | KL25        | ✔      |      | ✖         |                   |              |
+|              |         +-------------+--------+------+-----------+-------------------+--------------+
+|              |         | K32L2       | ✔      |      | ✖         |                   |              |
+|              +---------+-------------+--------+------+-----------+-------------------+--------------+
+|              | LPC     | 11u, 13, 15 | ✔      | ✖    | ✖         | lpc_ip3511        |              |
+|              |         +-------------+--------+------+-----------+-------------------+--------------+
+|              |         | 17, 40      | ✔      | ⚠    | ✖         | lpc17_40          |              |
+|              |         +-------------+--------+------+-----------+-------------------+--------------+
+|              |         | 18, 43      | ✔      | ✔    | ✔         | ci_hs             |              |
+|              |         +-------------+--------+------+-----------+-------------------+--------------+
+|              |         | 51u         | ✔      | ✖    | ✖         | lpc_ip3511        |              |
+|              |         +-------------+--------+------+-----------+-------------------+--------------+
+|              |         | 54          | ✔      |      | ✔         | lpc_ip3511        |              |
+|              |         +-------------+--------+------+-----------+-------------------+--------------+
+|              |         | 55          | ✔      |      | ✔         | lpc_ip3511        |              |
++--------------+---------+-------------+--------+------+-----------+-------------------+--------------+
+| Raspberry Pi | RP2040                | ✔      | ✔    | ✖         | rp2040            |              |
++--------------+-----------------------+--------+------+-----------+-------------------+--------------+
+| Renesas      | RX 63N, 65N, 72N      | ✔      | ✖    | ✖         | usba              |              |
++--------------+-----------------------+--------+------+-----------+-------------------+--------------+
+| Silabs       | EFM32GG12             | ✔      |      | ✖         | dwc2              |              |
++--------------+-----------------------+--------+------+-----------+-------------------+--------------+
+| Sony         | CXD56                 | ✔      | ✖    | ✔         | cxd56             |              |
++--------------+-----------------------+--------+------+-----------+-------------------+--------------+
+| ST STM32     | F0                    | ✔      | ✖    | ✖         | stm32_fsdev       |              |
+|              +----+------------------+--------+------+-----------+-------------------+--------------+
+|              | F1 | 102, 103         | ✔      | ✖    | ✖         | stm32_fsdev       |              |
+|              |    +------------------+--------+------+-----------+-------------------+--------------+
+|              |    | 105, 107         | ✔      |      | ✖         | dwc2              |              |
+|              +----+------------------+--------+------+-----------+-------------------+--------------+
+|              | F2                    | ✔      |      | ✔         | dwc2              |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | F3                    | ✔      | ✖    | ✖         | stm32_fsdev       |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | F4                    | ✔      |      | ✔         | dwc2              |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | F7                    | ✔      |      | ✔         | dwc2              |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | H7                    | ✔      |      | ✔         | dwc2              |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | L0, L1                | ✔      | ✖    | ✖         | stm32_fsdev       |              |
+|              +----+------------------+--------+------+-----------+-------------------+--------------+
+|              | L4 | 4x2, 4x3         | ✔      | ✖    | ✖         | stm32_fsdev       |              |
+|              |    +------------------+--------+------+-----------+-------------------+--------------+
+|              |    | 4x5, 4x6         | ✔      |      |           | dwc2              |              |
+|              +----+------------------+--------+------+-----------+-------------------+--------------+
+|              | L4+                   | ✔      |      |           | dwc2              |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | U5                    | ⚠      |      |           | dwc2              |              |
++--------------+-----------------------+--------+------+-----------+-------------------+--------------+
+| TI           | MSP430                | ✔      | ✖    | ✖         | msp430x5xx        |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | MSP432E4              | ✔      |      | ✖         | musb              |              |
+|              +-----------------------+--------+------+-----------+-------------------+--------------+
+|              | TM4C123               | ✔      |      | ✖         | musb              |              |
++--------------+-----------------------+--------+------+-----------+-------------------+--------------+
+| ValentyUSB   | eptri                 | ✔      | ✖    | ✖         | eptri             |              |
++--------------+-----------------------+--------+------+-----------+-------------------+--------------+
+
 
 Table Legend
 ------------
 
-================= ===================
-|:x:|             Not available
-|:red_square:|    Not supported
-|:yellow_square:| WIP/partial support
-|:green_square:|  Supported
-================= ===================
+= ===================
+✔ Supported
+⚠ WIP/partial support
+✖ Not supported
+= ===================
 
 Supported Boards
 ================
@@ -134,6 +122,11 @@ The board support code is only used for self-contained examples and testing. It
 
 The following boards are supported (sorted alphabetically):
 
+Broadcom
+--------
+
+-  `Raspberry Pi CM4 <https://www.raspberrypi.com/products/compute-module-4>`__
+
 Dialog DA146xx
 --------------
 
@@ -143,12 +136,17 @@ Dialog DA146xx
 Espressif ESP32-S2
 ------------------
 
--  Adafruit Feather ESP32-S2
+-  `Adafruit Feather ESP32-S2 <https://www.adafruit.com/product/5000>`__
 -  `Adafruit Magtag 2.9" E-Ink WiFi Display <https://www.adafruit.com/product/4800>`__
 -  `Adafruit Metro ESP32-S2 <https://www.adafruit.com/product/4775>`__
 -  `ESP32-S2-Kaluga-1 <https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-esp32-s2-kaluga-1-kit.html>`__
 -  `ESP32-S2-Saola-1 <https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/hw-reference/esp32s2/user-guide-saola-1-v1.2.html>`__
 
+GigaDevice
+----------
+
+-  `Sipeed Longan Nano <https://longan.sipeed.com/en/>`__
+
 Infineon
 ---------
 
@@ -243,7 +241,8 @@ iMX RT
 Kinetis
 ^^^^^^^
 
--  `FRDM-KL25Z <https://www.nxp.com/design/development-boards/freedom-development-boards/mcu-boards/freedom-development-platform-for-kinetis-kl14-kl15-kl24-kl25-mcus:FRDM-KL25Z>`__
+-  `Freedom FRDM-KL25Z <https://www.nxp.com/design/development-boards/freedom-development-boards/mcu-boards/freedom-development-platform-for-kinetis-kl14-kl15-kl24-kl25-mcus:FRDM-KL25Z>`__
+-  `Freedom FRDM-K32L2B3 <https://www.nxp.com/design/development-boards/freedom-development-boards/mcu-boards/nxp-freedom-development-platform-for-k32-l2b-mcus:FRDM-K32L2B3>`__
 
 LPC 11-13-15
 ^^^^^^^^^^^^
@@ -374,6 +373,8 @@ TI
 --
 
 -  `MSP430F5529 USB LaunchPad Evaluation Kit <http://www.ti.com/tool/MSP-EXP430F5529LP>`__
+-  `MSP-EXP432E401Y LaunchPad Evaluation Kit <https://www.ti.com/tool/MSP-EXP432E401Y>`__
+-  `TM4C123GXL LaunchPad Evaluation Kit <https://www.ti.com/tool/EK-TM4C123GXL>`__
 
 Tomu
 ----

+ 0 - 1
docs/requirements.txt

@@ -1,4 +1,3 @@
 sphinx~=3.0
 furo>=2020.12.30.b24
-sphinxemoji>=0.1.8
 sphinx-autodoc-typehints>=1.10

+ 6 - 8
examples/device/cdc_msc_freertos/src/main.c

@@ -38,12 +38,17 @@
   #include "freertos/queue.h"
   #include "freertos/task.h"
   #include "freertos/timers.h"
+
+  #define USBD_STACK_SIZE     4096
 #else
   #include "FreeRTOS.h"
   #include "semphr.h"
   #include "queue.h"
   #include "task.h"
   #include "timers.h"
+
+  // Increase stack size when debug log is enabled
+  #define USBD_STACK_SIZE    (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1)
 #endif
 
 //--------------------------------------------------------------------+
@@ -65,14 +70,7 @@ enum  {
 StaticTimer_t blinky_tmdef;
 TimerHandle_t blinky_tm;
 
-// static task for usbd
-// Increase stack size when debug log is enabled
-#if CFG_TUSB_DEBUG
-  #define USBD_STACK_SIZE     (3*configMINIMAL_STACK_SIZE)
-#else
-  #define USBD_STACK_SIZE     (3*configMINIMAL_STACK_SIZE/2)
-#endif
-
+// static task
 StackType_t  usb_device_stack[USBD_STACK_SIZE];
 StaticTask_t usb_device_taskdef;
 

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

@@ -39,12 +39,18 @@
   #include "freertos/queue.h"
   #include "freertos/task.h"
   #include "freertos/timers.h"
+
+  #define USBD_STACK_SIZE     4096
+
 #else
   #include "FreeRTOS.h"
   #include "semphr.h"
   #include "queue.h"
   #include "task.h"
   #include "timers.h"
+
+  // Increase stack size when debug log is enabled
+  #define USBD_STACK_SIZE    (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1)
 #endif
 
 //--------------------------------------------------------------------+
@@ -66,13 +72,7 @@ enum  {
 StaticTimer_t blinky_tmdef;
 TimerHandle_t blinky_tm;
 
-// static task for usbd
-#if CFG_TUSB_DEBUG
-  #define USBD_STACK_SIZE     (3*configMINIMAL_STACK_SIZE)
-#else
-  #define USBD_STACK_SIZE     (3*configMINIMAL_STACK_SIZE/2)
-#endif
-
+// static task
 StackType_t  usb_device_stack[USBD_STACK_SIZE];
 StaticTask_t usb_device_taskdef;
 

+ 0 - 2
examples/host/cdc_msc_hid/Makefile

@@ -20,9 +20,7 @@ SRC_C += \
 	src/host/hub.c \
 	src/host/usbh.c \
 	src/host/usbh_control.c \
-	src/portable/ehci/ehci.c \
 	src/portable/ohci/ohci.c \
-	src/portable/nxp/transdimension/hcd_transdimension.c \
 	src/portable/nxp/lpc17_40/hcd_lpc17_40.c \
 	src/portable/mentor/musb/hcd_musb.c
 

+ 0 - 2
examples/host/hid_controller/Makefile

@@ -23,9 +23,7 @@ SRC_C += \
 	src/host/hub.c \
 	src/host/usbh.c \
 	src/host/usbh_control.c \
-	src/portable/ehci/ehci.c \
 	src/portable/ohci/ohci.c \
-	src/portable/nxp/transdimension/hcd_transdimension.c \
 	src/portable/nxp/lpc17_40/hcd_lpc17_40.c \
 	src/portable/mentor/musb/hcd_musb.c
 

+ 3 - 1
hw/bsp/ea4357/board.mk

@@ -21,7 +21,9 @@ MCU_DIR = hw/mcu/nxp/lpcopen/lpc43xx/lpc_chip_43xx
 LD_FILE = hw/bsp/$(BOARD)/lpc4357.ld
 
 SRC_C += \
-	src/portable/nxp/transdimension/dcd_transdimension.c \
+	src/portable/chipidea/ci_hs/dcd_ci_hs.c \
+	src/portable/chipidea/ci_hs/hcd_ci_hs.c \
+	src/portable/ehci/ehci.c \
 	$(MCU_DIR)/../gcc/cr_startup_lpc43xx.c \
 	$(MCU_DIR)/src/chip_18xx_43xx.c \
 	$(MCU_DIR)/src/clock_18xx_43xx.c \

+ 3 - 1
hw/bsp/imxrt/family.mk

@@ -28,7 +28,9 @@ LDFLAGS += \
 	-Wl,--defsym,__stack_size__=0x800 \
 
 SRC_C += \
-	src/portable/nxp/transdimension/dcd_transdimension.c \
+	src/portable/chipidea/ci_hs/dcd_ci_hs.c \
+	src/portable/chipidea/ci_hs/hcd_ci_hs.c \
+	src/portable/ehci/ehci.c \
 	$(MCU_DIR)/system_$(MCU_VARIANT).c \
 	$(MCU_DIR)/xip/fsl_flexspi_nor_boot.c \
 	$(MCU_DIR)/project_template/clock_config.c \

+ 3 - 1
hw/bsp/lpc18/family.mk

@@ -18,7 +18,9 @@ CFLAGS += -Wno-error=unused-parameter -Wno-error=strict-prototypes -Wno-error=ca
 MCU_DIR = hw/mcu/nxp/lpcopen/lpc18xx/lpc_chip_18xx
 
 SRC_C += \
-	src/portable/nxp/transdimension/dcd_transdimension.c \
+	src/portable/chipidea/ci_hs/dcd_ci_hs.c \
+	src/portable/chipidea/ci_hs/hcd_ci_hs.c \
+	src/portable/ehci/ehci.c \
 	$(MCU_DIR)/../gcc/cr_startup_lpc18xx.c \
 	$(MCU_DIR)/src/chip_18xx_43xx.c \
 	$(MCU_DIR)/src/clock_18xx_43xx.c \

+ 3 - 1
hw/bsp/ngx4330/board.mk

@@ -21,7 +21,9 @@ MCU_DIR = hw/mcu/nxp/lpcopen/lpc43xx/lpc_chip_43xx
 LD_FILE = hw/bsp/$(BOARD)/ngx4330.ld
 
 SRC_C += \
-	src/portable/nxp/transdimension/dcd_transdimension.c \
+	src/portable/chipidea/ci_hs/dcd_ci_hs.c \
+	src/portable/chipidea/ci_hs/hcd_ci_hs.c \
+	src/portable/ehci/ehci.c \
 	$(MCU_DIR)/../gcc/cr_startup_lpc43xx.c \
 	$(MCU_DIR)/src/chip_18xx_43xx.c \
 	$(MCU_DIR)/src/clock_18xx_43xx.c \

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

@@ -310,8 +310,8 @@ static inline bool  tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y
   HID_COLLECTION_END \
 
 // Gamepad Report Descriptor Template
-// with 16 buttons, 2 joysticks and 1 hat/dpad with following layout
-// | X | Y | Z | Rz | Rx | Ry (1 byte each) | hat/DPAD (1 byte) | Button Map (2 bytes) |
+// with 32 buttons, 2 joysticks and 1 hat/dpad with following layout
+// | X | Y | Z | Rz | Rx | Ry (1 byte each) | hat/DPAD (1 byte) | Button Map (4 bytes) |
 #define TUD_HID_REPORT_DESC_GAMEPAD(...) \
   HID_USAGE_PAGE ( HID_USAGE_PAGE_DESKTOP     )                 ,\
   HID_USAGE      ( HID_USAGE_DESKTOP_GAMEPAD  )                 ,\
@@ -319,37 +319,37 @@ static inline bool  tud_hid_gamepad_report(uint8_t report_id, int8_t x, int8_t y
     /* Report ID if any */\
     __VA_ARGS__ \
     /* 8 bit X, Y, Z, Rz, Rx, Ry (min -127, max 127 ) */ \
-    HID_USAGE_PAGE   ( HID_USAGE_PAGE_DESKTOP                 ) ,\
-    HID_USAGE        ( HID_USAGE_DESKTOP_X                    ) ,\
-    HID_USAGE        ( HID_USAGE_DESKTOP_Y                    ) ,\
-    HID_USAGE        ( HID_USAGE_DESKTOP_Z                    ) ,\
-    HID_USAGE        ( HID_USAGE_DESKTOP_RZ                   ) ,\
-    HID_USAGE        ( HID_USAGE_DESKTOP_RX                   ) ,\
-    HID_USAGE        ( HID_USAGE_DESKTOP_RY                   ) ,\
-    HID_LOGICAL_MIN  ( 0x81                                   ) ,\
-    HID_LOGICAL_MAX  ( 0x7f                                   ) ,\
-    HID_REPORT_COUNT ( 6                                      ) ,\
-    HID_REPORT_SIZE  ( 8                                      ) ,\
-    HID_INPUT        ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
+    HID_USAGE_PAGE     ( HID_USAGE_PAGE_DESKTOP                 ) ,\
+    HID_USAGE          ( HID_USAGE_DESKTOP_X                    ) ,\
+    HID_USAGE          ( HID_USAGE_DESKTOP_Y                    ) ,\
+    HID_USAGE          ( HID_USAGE_DESKTOP_Z                    ) ,\
+    HID_USAGE          ( HID_USAGE_DESKTOP_RZ                   ) ,\
+    HID_USAGE          ( HID_USAGE_DESKTOP_RX                   ) ,\
+    HID_USAGE          ( HID_USAGE_DESKTOP_RY                   ) ,\
+    HID_LOGICAL_MIN    ( 0x81                                   ) ,\
+    HID_LOGICAL_MAX    ( 0x7f                                   ) ,\
+    HID_REPORT_COUNT   ( 6                                      ) ,\
+    HID_REPORT_SIZE    ( 8                                      ) ,\
+    HID_INPUT          ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
     /* 8 bit DPad/Hat Button Map  */ \
-    HID_USAGE_PAGE   ( HID_USAGE_PAGE_DESKTOP                 ) ,\
-    HID_USAGE        ( HID_USAGE_DESKTOP_HAT_SWITCH           ) ,\
-    HID_LOGICAL_MIN  ( 1                                      ) ,\
-    HID_LOGICAL_MAX  ( 8                                      ) ,\
-    HID_PHYSICAL_MIN ( 0                                      ) ,\
-    HID_PHYSICAL_MAX_N ( 315, 2                               ) ,\
-    HID_REPORT_COUNT ( 1                                      ) ,\
-    HID_REPORT_SIZE  ( 8                                      ) ,\
-    HID_INPUT        ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
-    /* 16 bit Button Map */ \
-    HID_USAGE_PAGE   ( HID_USAGE_PAGE_BUTTON                  ) ,\
-    HID_USAGE_MIN    ( 1                                      ) ,\
-    HID_USAGE_MAX    ( 32                                     ) ,\
-    HID_LOGICAL_MIN  ( 0                                      ) ,\
-    HID_LOGICAL_MAX  ( 1                                      ) ,\
-    HID_REPORT_COUNT ( 32                                     ) ,\
-    HID_REPORT_SIZE  ( 1                                      ) ,\
-    HID_INPUT        ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
+    HID_USAGE_PAGE     ( HID_USAGE_PAGE_DESKTOP                 ) ,\
+    HID_USAGE          ( HID_USAGE_DESKTOP_HAT_SWITCH           ) ,\
+    HID_LOGICAL_MIN    ( 1                                      ) ,\
+    HID_LOGICAL_MAX    ( 8                                      ) ,\
+    HID_PHYSICAL_MIN   ( 0                                      ) ,\
+    HID_PHYSICAL_MAX_N ( 315, 2                                 ) ,\
+    HID_REPORT_COUNT   ( 1                                      ) ,\
+    HID_REPORT_SIZE    ( 8                                      ) ,\
+    HID_INPUT          ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
+    /* 32 bit Button Map */ \
+    HID_USAGE_PAGE     ( HID_USAGE_PAGE_BUTTON                  ) ,\
+    HID_USAGE_MIN      ( 1                                      ) ,\
+    HID_USAGE_MAX      ( 32                                     ) ,\
+    HID_LOGICAL_MIN    ( 0                                      ) ,\
+    HID_LOGICAL_MAX    ( 1                                      ) ,\
+    HID_REPORT_COUNT   ( 32                                     ) ,\
+    HID_REPORT_SIZE    ( 1                                      ) ,\
+    HID_INPUT          ( HID_DATA | HID_VARIABLE | HID_ABSOLUTE ) ,\
   HID_COLLECTION_END \
 
 // HID Generic Input & Output

+ 2 - 0
src/device/dcd_attr.h

@@ -44,6 +44,7 @@
 
 #elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX)
   // TODO USB0 has 6, USB1 has 4
+  #define DCD_ATTR_CONTROLLER_CHIPIDEA_HS
   #define DCD_ATTR_ENDPOINT_MAX   6
 
 #elif TU_CHECK_MCU(OPT_MCU_LPC51UXX)
@@ -58,6 +59,7 @@
   #define DCD_ATTR_ENDPOINT_MAX   6
 
 #elif TU_CHECK_MCU(OPT_MCU_MIMXRT10XX)
+  #define DCD_ATTR_CONTROLLER_CHIPIDEA_HS
   #define DCD_ATTR_ENDPOINT_MAX   8
 
 #elif TU_CHECK_MCU(OPT_MCU_MKL25ZXX, OPT_MCU_K32L2BXX)

+ 4 - 2
src/host/usbh.c

@@ -541,10 +541,12 @@ void process_device_unplugged(uint8_t rhport, uint8_t hub_addr, uint8_t hub_port
         usbh_class_drivers[drv_id].close(dev_addr);
       }
 
+      hcd_device_close(rhport, dev_addr);
+
+      // release all endpoints associated with the device
       memset(dev->itf2drv, DRVID_INVALID, sizeof(dev->itf2drv)); // invalid mapping
       memset(dev->ep2drv , DRVID_INVALID, sizeof(dev->ep2drv )); // invalid mapping
-
-      hcd_device_close(rhport, dev_addr);
+      tu_memclr(dev->ep_status, sizeof(dev->ep_status));
 
       dev->state = TUSB_DEVICE_STATE_UNPLUG;
     }

+ 50 - 0
src/portable/chipidea/ci_hs/ci_hs_imxrt.h

@@ -0,0 +1,50 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021, 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 _CI_HS_IMXRT_H_
+#define _CI_HS_IMXRT_H_
+
+#include "fsl_device_registers.h"
+
+static const ci_hs_controller_t _ci_controller[] =
+{
+  // RT1010 and RT1020 only has 1 USB controller
+  #if FSL_FEATURE_SOC_USBHS_COUNT == 1
+    { .reg_base = USB_BASE , .irqnum = USB_OTG1_IRQn, .ep_count = 8 }
+  #else
+    { .reg_base = USB1_BASE, .irqnum = USB_OTG1_IRQn, .ep_count = 8 },
+    { .reg_base = USB2_BASE, .irqnum = USB_OTG2_IRQn, .ep_count = 8 }
+  #endif
+};
+
+#define CI_DCD_INT_ENABLE(_p)   NVIC_EnableIRQ (_ci_controller[_p].irqnum)
+#define CI_DCD_INT_DISABLE(_p)  NVIC_DisableIRQ(_ci_controller[_p].irqnum)
+
+#define CI_HCD_INT_ENABLE(_p)   NVIC_EnableIRQ (_ci_controller[_p].irqnum)
+#define CI_HCD_INT_DISABLE(_p)  NVIC_DisableIRQ(_ci_controller[_p].irqnum)
+
+
+#endif

+ 45 - 0
src/portable/chipidea/ci_hs/ci_hs_lpc18_43.h

@@ -0,0 +1,45 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021, 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 _CI_HS_LPC18_43_H_
+#define _CI_HS_LPC18_43_H_
+
+// LPCOpen for 18xx & 43xx
+#include "chip.h"
+
+static const ci_hs_controller_t _ci_controller[] =
+{
+  { .reg_base = LPC_USB0_BASE, .irqnum = USB0_IRQn, .ep_count = 6 },
+  { .reg_base = LPC_USB1_BASE, .irqnum = USB1_IRQn, .ep_count = 4 }
+};
+
+#define CI_DCD_INT_ENABLE(_p)   NVIC_EnableIRQ (_ci_controller[_p].irqnum)
+#define CI_DCD_INT_DISABLE(_p)  NVIC_DisableIRQ(_ci_controller[_p].irqnum)
+
+#define CI_HCD_INT_ENABLE(_p)   NVIC_EnableIRQ (_ci_controller[_p].irqnum)
+#define CI_HCD_INT_DISABLE(_p)  NVIC_DisableIRQ(_ci_controller[_p].irqnum)
+
+#endif

+ 144 - 0
src/portable/chipidea/ci_hs/ci_hs_type.h

@@ -0,0 +1,144 @@
+/* 
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2021, 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 CI_HS_TYPE_H_
+#define CI_HS_TYPE_H_
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+// USBCMD
+enum {
+  USBCMD_RUN_STOP         = TU_BIT(0),
+  USBCMD_RESET            = TU_BIT(1),
+  USBCMD_SETUP_TRIPWIRE   = TU_BIT(13),
+  USBCMD_ADD_QTD_TRIPWIRE = TU_BIT(14)  ///< This bit is used as a semaphore to ensure the to proper addition of a new dTD to an active (primed) endpoint’s linked list. This bit is set and cleared by software during the process of adding a new dTD
+// Interrupt Threshold bit 23:16
+};
+
+// PORTSC1
+#define PORTSC1_PORT_SPEED_POS    26
+
+enum {
+  PORTSC1_CURRENT_CONNECT_STATUS = TU_BIT(0),
+  PORTSC1_FORCE_PORT_RESUME      = TU_BIT(6),
+  PORTSC1_SUSPEND                = TU_BIT(7),
+  PORTSC1_FORCE_FULL_SPEED       = TU_BIT(24),
+  PORTSC1_PORT_SPEED             = TU_BIT(26) | TU_BIT(27)
+};
+
+// OTGSC
+enum {
+  OTGSC_VBUS_DISCHARGE          = TU_BIT(0),
+  OTGSC_VBUS_CHARGE             = TU_BIT(1),
+//  OTGSC_HWASSIST_AUTORESET    = TU_BIT(2),
+  OTGSC_OTG_TERMINATION         = TU_BIT(3), ///< Must set to 1 when OTG go to device mode
+  OTGSC_DATA_PULSING            = TU_BIT(4),
+  OTGSC_ID_PULLUP               = TU_BIT(5),
+//  OTGSC_HWASSIT_DATA_PULSE    = TU_BIT(6),
+//  OTGSC_HWASSIT_BDIS_ACONN    = TU_BIT(7),
+  OTGSC_ID                      = TU_BIT(8), ///< 0 = A device, 1 = B Device
+  OTGSC_A_VBUS_VALID            = TU_BIT(9),
+  OTGSC_A_SESSION_VALID         = TU_BIT(10),
+  OTGSC_B_SESSION_VALID         = TU_BIT(11),
+  OTGSC_B_SESSION_END           = TU_BIT(12),
+  OTGSC_1MS_TOGGLE              = TU_BIT(13),
+  OTGSC_DATA_BUS_PULSING_STATUS = TU_BIT(14),
+};
+
+// USBMode
+enum {
+  USBMODE_CM_DEVICE = 2,
+  USBMODE_CM_HOST   = 3,
+
+  USBMODE_SLOM = TU_BIT(3),
+  USBMODE_SDIS = TU_BIT(4),
+
+  USBMODE_VBUS_POWER_SELECT = TU_BIT(5), // Need to be enabled for LPC18XX/43XX in host mode
+};
+
+// Device Registers
+typedef struct
+{
+  //------------- ID + HW Parameter Registers-------------//
+  volatile uint32_t TU_RESERVED[64]; ///< For iMX RT10xx, but not used by LPC18XX/LPC43XX
+
+  //------------- Capability Registers-------------//
+  volatile uint8_t  CAPLENGTH;       ///< Capability Registers Length
+  volatile uint8_t  TU_RESERVED[1];
+  volatile uint16_t HCIVERSION;      ///< Host Controller Interface Version
+
+  volatile uint32_t HCSPARAMS;       ///< Host Controller Structural Parameters
+  volatile uint32_t HCCPARAMS;       ///< Host Controller Capability Parameters
+  volatile uint32_t TU_RESERVED[5];
+
+  volatile uint16_t DCIVERSION;      ///< Device Controller Interface Version
+  volatile uint8_t  TU_RESERVED[2];
+
+  volatile uint32_t DCCPARAMS;       ///< Device Controller Capability Parameters
+  volatile uint32_t TU_RESERVED[6];
+
+  //------------- Operational Registers -------------//
+  volatile uint32_t USBCMD;          ///< USB Command Register
+  volatile uint32_t USBSTS;          ///< USB Status Register
+  volatile uint32_t USBINTR;         ///< Interrupt Enable Register
+  volatile uint32_t FRINDEX;         ///< USB Frame Index
+  volatile uint32_t TU_RESERVED;
+  volatile uint32_t DEVICEADDR;      ///< Device Address
+  volatile uint32_t ENDPTLISTADDR;   ///< Endpoint List Address
+  volatile uint32_t TU_RESERVED;
+  volatile uint32_t BURSTSIZE;       ///< Programmable Burst Size
+  volatile uint32_t TXFILLTUNING;    ///< TX FIFO Fill Tuning
+           uint32_t TU_RESERVED[4];
+  volatile uint32_t ENDPTNAK;        ///< Endpoint NAK
+  volatile uint32_t ENDPTNAKEN;      ///< Endpoint NAK Enable
+  volatile uint32_t TU_RESERVED;
+  volatile uint32_t PORTSC1;         ///< Port Status & Control
+  volatile uint32_t TU_RESERVED[7];
+  volatile uint32_t OTGSC;           ///< On-The-Go Status & control
+  volatile uint32_t USBMODE;         ///< USB Device Mode
+  volatile uint32_t ENDPTSETUPSTAT;  ///< Endpoint Setup Status
+  volatile uint32_t ENDPTPRIME;      ///< Endpoint Prime
+  volatile uint32_t ENDPTFLUSH;      ///< Endpoint Flush
+  volatile uint32_t ENDPTSTAT;       ///< Endpoint Status
+  volatile uint32_t ENDPTCOMPLETE;   ///< Endpoint Complete
+  volatile uint32_t ENDPTCTRL[8];    ///< Endpoint Control 0 - 7
+} ci_hs_regs_t;
+
+
+typedef struct
+{
+  uint32_t reg_base;
+  uint32_t irqnum;
+  uint8_t  ep_count; // Max bi-directional Endpoints
+}ci_hs_controller_t;
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif /* CI_HS_TYPE_H_ */

+ 637 - 0
src/portable/chipidea/ci_hs/dcd_ci_hs.c

@@ -0,0 +1,637 @@
+/*
+ * 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"
+#include "device/dcd_attr.h"
+
+#if TUSB_OPT_DEVICE_ENABLED && defined(DCD_ATTR_CONTROLLER_CHIPIDEA_HS)
+
+//--------------------------------------------------------------------+
+// INCLUDE
+//--------------------------------------------------------------------+
+#include "device/dcd.h"
+#include "ci_hs_type.h"
+
+#if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX
+  #include "ci_hs_imxrt.h"
+#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX)
+  #include "ci_hs_lpc18_43.h"
+#else
+  #error "Unsupported MCUs"
+#endif
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF
+//--------------------------------------------------------------------+
+
+#define CI_HS_REG(_port)      ((ci_hs_regs_t*) _ci_controller[_port].reg_base)
+
+#if defined(__CORTEX_M) && __CORTEX_M == 7 && __DCACHE_PRESENT == 1
+  #define CleanInvalidateDCache_by_Addr   SCB_CleanInvalidateDCache_by_Addr
+#else
+  #define CleanInvalidateDCache_by_Addr(_addr, _dsize)
+#endif
+
+
+// ENDPTCTRL
+enum {
+  ENDPTCTRL_STALL          = TU_BIT(0),
+  ENDPTCTRL_TOGGLE_INHIBIT = TU_BIT(5), // used for test only
+  ENDPTCTRL_TOGGLE_RESET   = TU_BIT(6),
+  ENDPTCTRL_ENABLE         = TU_BIT(7)
+};
+
+enum {
+  ENDPTCTRL_TYPE_POS  = 2, // Endpoint type is 2-bit field
+};
+
+// USBSTS, USBINTR
+enum {
+  INTR_USB         = TU_BIT(0),
+  INTR_ERROR       = TU_BIT(1),
+  INTR_PORT_CHANGE = TU_BIT(2),
+  INTR_RESET       = TU_BIT(6),
+  INTR_SOF         = TU_BIT(7),
+  INTR_SUSPEND     = TU_BIT(8),
+  INTR_NAK         = TU_BIT(16)
+};
+
+// Queue Transfer Descriptor
+typedef struct
+{
+  // Word 0: Next QTD Pointer
+  uint32_t next; ///< Next link pointer This field contains the physical memory address of the next dTD to be processed
+
+  // Word 1: qTQ Token
+  uint32_t                      : 3  ;
+  volatile uint32_t xact_err    : 1  ;
+  uint32_t                      : 1  ;
+  volatile uint32_t buffer_err  : 1  ;
+  volatile uint32_t halted      : 1  ;
+  volatile uint32_t active      : 1  ;
+  uint32_t                      : 2  ;
+  uint32_t iso_mult_override    : 2  ; ///< This field can be used for transmit ISOs to override the MULT field in the dQH. This field must be zero for all packet types that are not transmit-ISO.
+  uint32_t                      : 3  ;
+  uint32_t int_on_complete      : 1  ;
+  volatile uint32_t total_bytes : 15 ;
+  uint32_t                      : 1  ;
+
+  // Word 2-6: 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]; ///< buffer1 has frame_n for TODO Isochronous
+
+  //--------------------------------------------------------------------+
+  // TD is 32 bytes aligned but occupies only 28 bytes
+  // Therefore there are 4 bytes padding that we can use.
+  //--------------------------------------------------------------------+
+  uint16_t expected_bytes;
+  uint8_t reserved[2];
+} dcd_qtd_t;
+
+TU_VERIFY_STATIC( sizeof(dcd_qtd_t) == 32, "size is not correct");
+
+// Queue Head
+typedef struct
+{
+  // Word 0: Capabilities and Characteristics
+  uint32_t                         : 15 ; ///< Number of packets executed per transaction descriptor 00 - Execute N transactions as demonstrated by the USB variable length protocol where N is computed using Max_packet_length and the Total_bytes field in the dTD. 01 - Execute one transaction 10 - Execute two transactions 11 - Execute three transactions Remark: Non-isochronous endpoints must set MULT = 00. Remark: Isochronous endpoints must set MULT = 01, 10, or 11 as needed.
+  uint32_t int_on_setup            : 1  ; ///< Interrupt on setup This bit is used on control type endpoints to indicate if USBINT is set in response to a setup being received.
+  uint32_t max_packet_size         : 11 ; ///< Endpoint's wMaxPacketSize
+  uint32_t                         : 2  ;
+  uint32_t zero_length_termination : 1  ; ///< This bit is used for non-isochronous endpoints to indicate when a zero-length packet is received to terminate transfers in case the total transfer length is “multiple”. 0 - Enable zero-length packet to terminate transfers equal to a multiple of Max_packet_length (default). 1 - Disable zero-length packet on transfers that are equal in length to a multiple Max_packet_length.
+  uint32_t iso_mult                : 2  ; ///<
+
+  // Word 1: Current qTD Pointer
+  volatile uint32_t qtd_addr;
+
+  // Word 2-9: Transfer Overlay
+  volatile dcd_qtd_t qtd_overlay;
+
+  // Word 10-11: Setup request (control OUT only)
+  volatile tusb_control_request_t setup_request;
+
+  //--------------------------------------------------------------------+
+  // QHD is 64 bytes aligned but occupies only 48 bytes
+  // Therefore there are 16 bytes padding that we can use.
+  //--------------------------------------------------------------------+
+  tu_fifo_t * ff;
+  uint8_t reserved[12];
+} dcd_qhd_t;
+
+TU_VERIFY_STATIC( sizeof(dcd_qhd_t) == 64, "size is not correct");
+
+//--------------------------------------------------------------------+
+// Variables
+//--------------------------------------------------------------------+
+
+#define QTD_NEXT_INVALID 0x01
+
+typedef struct {
+  // Must be at 2K alignment
+  // Each endpoint with direction (IN/OUT) occupies a queue head
+  // for portability, TinyUSB only queue 1 TD for each Qhd
+  dcd_qhd_t qhd[DCD_ATTR_ENDPOINT_MAX][2] TU_ATTR_ALIGNED(64);
+  dcd_qtd_t qtd[DCD_ATTR_ENDPOINT_MAX][2] TU_ATTR_ALIGNED(32);
+}dcd_data_t;
+
+CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(2048)
+static dcd_data_t _dcd_data;
+
+//--------------------------------------------------------------------+
+// Controller API
+//--------------------------------------------------------------------+
+
+/// follows LPC43xx User Manual 23.10.3
+static void bus_reset(uint8_t rhport)
+{
+  ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
+
+  // The reset value for all endpoint types is the control endpoint. If one endpoint
+  // direction is enabled and the paired endpoint of opposite direction is disabled, then the
+  // endpoint type of the unused direction must be changed from the control type to any other
+  // type (e.g. bulk). Leaving an un-configured endpoint control will cause undefined behavior
+  // for the data PID tracking on the active endpoint.
+  for( uint8_t i=1; i < _ci_controller[rhport].ep_count; i++)
+  {
+    dcd_reg->ENDPTCTRL[i] = (TUSB_XFER_BULK << ENDPTCTRL_TYPE_POS) | (TUSB_XFER_BULK << (16+ENDPTCTRL_TYPE_POS));
+  }
+
+  //------------- Clear All Registers -------------//
+  dcd_reg->ENDPTNAK       = dcd_reg->ENDPTNAK;
+  dcd_reg->ENDPTNAKEN     = 0;
+  dcd_reg->USBSTS         = dcd_reg->USBSTS;
+  dcd_reg->ENDPTSETUPSTAT = dcd_reg->ENDPTSETUPSTAT;
+  dcd_reg->ENDPTCOMPLETE  = dcd_reg->ENDPTCOMPLETE;
+
+  while (dcd_reg->ENDPTPRIME) {}
+  dcd_reg->ENDPTFLUSH = 0xFFFFFFFF;
+  while (dcd_reg->ENDPTFLUSH) {}
+
+  // read reset bit in portsc
+
+  //------------- Queue Head & Queue TD -------------//
+  tu_memclr(&_dcd_data, sizeof(dcd_data_t));
+
+  //------------- Set up Control Endpoints (0 OUT, 1 IN) -------------//
+  _dcd_data.qhd[0][0].zero_length_termination = _dcd_data.qhd[0][1].zero_length_termination = 1;
+  _dcd_data.qhd[0][0].max_packet_size  = _dcd_data.qhd[0][1].max_packet_size  = CFG_TUD_ENDPOINT0_SIZE;
+  _dcd_data.qhd[0][0].qtd_overlay.next = _dcd_data.qhd[0][1].qtd_overlay.next = QTD_NEXT_INVALID;
+
+  _dcd_data.qhd[0][0].int_on_setup = 1; // OUT only
+}
+
+void dcd_init(uint8_t rhport)
+{
+  tu_memclr(&_dcd_data, sizeof(dcd_data_t));
+
+  ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
+
+  // Reset controller
+  dcd_reg->USBCMD |= USBCMD_RESET;
+  while( dcd_reg->USBCMD & USBCMD_RESET ) {}
+
+  // Set mode to device, must be set immediately after reset
+  dcd_reg->USBMODE = USBMODE_CM_DEVICE;
+  dcd_reg->OTGSC = OTGSC_VBUS_DISCHARGE | OTGSC_OTG_TERMINATION;
+
+#if !TUD_OPT_HIGH_SPEED
+  dcd_reg->PORTSC1 = PORTSC1_FORCE_FULL_SPEED;
+#endif
+
+  CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
+
+  dcd_reg->ENDPTLISTADDR = (uint32_t) _dcd_data.qhd; // Endpoint List Address has to be 2K alignment
+  dcd_reg->USBSTS  = dcd_reg->USBSTS;
+  dcd_reg->USBINTR = INTR_USB | INTR_ERROR | INTR_PORT_CHANGE | INTR_SUSPEND;
+
+  dcd_reg->USBCMD &= ~0x00FF0000;     // Interrupt Threshold Interval = 0
+  dcd_reg->USBCMD |= USBCMD_RUN_STOP; // Connect
+}
+
+void dcd_int_enable(uint8_t rhport)
+{
+  CI_DCD_INT_ENABLE(rhport);
+}
+
+void dcd_int_disable(uint8_t rhport)
+{
+  CI_DCD_INT_DISABLE(rhport);
+}
+
+void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
+{
+  // Response with status first before changing device address
+  dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0);
+
+  ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
+  dcd_reg->DEVICEADDR = (dev_addr << 25) | TU_BIT(24);
+}
+
+void dcd_remote_wakeup(uint8_t rhport)
+{
+  ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
+  dcd_reg->PORTSC1 |= PORTSC1_FORCE_PORT_RESUME;
+}
+
+void dcd_connect(uint8_t rhport)
+{
+  ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
+  dcd_reg->USBCMD |= USBCMD_RUN_STOP;
+}
+
+void dcd_disconnect(uint8_t rhport)
+{
+  ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
+  dcd_reg->USBCMD &= ~USBCMD_RUN_STOP;
+}
+
+//--------------------------------------------------------------------+
+// HELPER
+//--------------------------------------------------------------------+
+
+static void qtd_init(dcd_qtd_t* p_qtd, void * data_ptr, uint16_t total_bytes)
+{
+  // Force the CPU to flush the buffer. We increase the size by 31 because the call aligns the
+  // address to 32-byte boundaries. Buffer must be word aligned
+  CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) data_ptr, 4), total_bytes + 31);
+
+  tu_memclr(p_qtd, sizeof(dcd_qtd_t));
+
+  p_qtd->next            = QTD_NEXT_INVALID;
+  p_qtd->active          = 1;
+  p_qtd->total_bytes     = p_qtd->expected_bytes = total_bytes;
+  p_qtd->int_on_complete = true;
+
+  if (data_ptr != NULL)
+  {
+    p_qtd->buffer[0] = (uint32_t) data_ptr;
+
+    uint32_t const bufend = p_qtd->buffer[0] + total_bytes;
+    for(uint8_t i=1; i<5; i++)
+    {
+      uint32_t const next_page = tu_align4k( p_qtd->buffer[i-1] ) + 4096;
+      if ( bufend <= next_page ) break;
+
+      p_qtd->buffer[i] = next_page;
+
+      // TODO page[1] FRAME_N for ISO transfer
+    }
+  }
+}
+
+//--------------------------------------------------------------------+
+// DCD Endpoint Port
+//--------------------------------------------------------------------+
+void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr)
+{
+  uint8_t const epnum  = tu_edpt_number(ep_addr);
+  uint8_t const dir    = tu_edpt_dir(ep_addr);
+
+  ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
+  dcd_reg->ENDPTCTRL[epnum] |= ENDPTCTRL_STALL << (dir ? 16 : 0);
+
+  // flush to abort any primed buffer
+  dcd_reg->ENDPTFLUSH = TU_BIT(epnum + (dir ? 16 : 0));
+}
+
+void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr)
+{
+  uint8_t const epnum = tu_edpt_number(ep_addr);
+  uint8_t const dir   = tu_edpt_dir(ep_addr);
+
+  // data toggle also need to be reset
+  ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
+  dcd_reg->ENDPTCTRL[epnum] |= ENDPTCTRL_TOGGLE_RESET << ( dir ? 16 : 0 );
+  dcd_reg->ENDPTCTRL[epnum] &= ~(ENDPTCTRL_STALL << ( dir  ? 16 : 0));
+}
+
+bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc)
+{
+  uint8_t const epnum = tu_edpt_number(p_endpoint_desc->bEndpointAddress);
+  uint8_t const dir   = tu_edpt_dir(p_endpoint_desc->bEndpointAddress);
+
+  // Must not exceed max endpoint number
+  TU_ASSERT( epnum < _ci_controller[rhport].ep_count );
+
+  //------------- Prepare Queue Head -------------//
+  dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir];
+  tu_memclr(p_qhd, sizeof(dcd_qhd_t));
+
+  p_qhd->zero_length_termination = 1;
+  p_qhd->max_packet_size         = tu_edpt_packet_size(p_endpoint_desc);
+  if (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS)
+  {
+    p_qhd->iso_mult = 1;
+  }
+
+  p_qhd->qtd_overlay.next        = QTD_NEXT_INVALID;
+
+  CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
+
+  // Enable EP Control
+  ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
+
+  uint32_t const epctrl = (p_endpoint_desc->bmAttributes.xfer << ENDPTCTRL_TYPE_POS) | ENDPTCTRL_ENABLE | ENDPTCTRL_TOGGLE_RESET;
+
+  if ( dir == TUSB_DIR_OUT )
+  {
+    dcd_reg->ENDPTCTRL[epnum] = (dcd_reg->ENDPTCTRL[epnum] & 0xFFFF0000u) | epctrl;
+  }else
+  {
+    dcd_reg->ENDPTCTRL[epnum] = (dcd_reg->ENDPTCTRL[epnum] & 0x0000FFFFu) | (epctrl << 16);
+  }
+
+  return true;
+}
+
+void dcd_edpt_close_all (uint8_t rhport)
+{
+  ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
+
+  // Disable all non-control endpoints
+  for( uint8_t epnum=1; epnum < _ci_controller[rhport].ep_count; epnum++)
+  {
+    _dcd_data.qhd[epnum][TUSB_DIR_OUT].qtd_overlay.halted = 1;
+    _dcd_data.qhd[epnum][TUSB_DIR_IN ].qtd_overlay.halted = 1;
+
+    dcd_reg->ENDPTFLUSH = TU_BIT(epnum) |  TU_BIT(epnum+16);
+    dcd_reg->ENDPTCTRL[epnum] = (TUSB_XFER_BULK << ENDPTCTRL_TYPE_POS) | (TUSB_XFER_BULK << (16+ENDPTCTRL_TYPE_POS));
+  }
+}
+
+void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr)
+{
+  uint8_t const epnum  = tu_edpt_number(ep_addr);
+  uint8_t const dir    = tu_edpt_dir(ep_addr);
+
+  ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
+
+  _dcd_data.qhd[epnum][dir].qtd_overlay.halted = 1;
+
+  // Flush EP
+  uint32_t const flush_mask = TU_BIT(epnum + (dir ? 16 : 0));
+  dcd_reg->ENDPTFLUSH = flush_mask;
+  while(dcd_reg->ENDPTFLUSH & flush_mask);
+
+  // Clear EP enable
+  dcd_reg->ENDPTCTRL[epnum] &=~(ENDPTCTRL_ENABLE << (dir ? 16 : 0));
+}
+
+static void qhd_start_xfer(uint8_t rhport, uint8_t epnum, uint8_t dir)
+{
+  ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
+  dcd_qhd_t* p_qhd = &_dcd_data.qhd[epnum][dir];
+  dcd_qtd_t* p_qtd = &_dcd_data.qtd[epnum][dir];
+
+  p_qhd->qtd_overlay.halted = false;            // clear any previous error
+  p_qhd->qtd_overlay.next   = (uint32_t) p_qtd; // link qtd to qhd
+
+  // flush cache
+  CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
+
+  if ( epnum == 0 )
+  {
+    // follows UM 24.10.8.1.1 Setup packet handling using setup lockout mechanism
+    // wait until ENDPTSETUPSTAT before priming data/status in response TODO add time out
+    while(dcd_reg->ENDPTSETUPSTAT & TU_BIT(0)) {}
+  }
+
+  // start transfer
+  dcd_reg->ENDPTPRIME = TU_BIT(epnum + (dir ? 16 : 0));
+}
+
+bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes)
+{
+  uint8_t const epnum = tu_edpt_number(ep_addr);
+  uint8_t const dir   = tu_edpt_dir(ep_addr);
+
+  dcd_qhd_t* p_qhd = &_dcd_data.qhd[epnum][dir];
+  dcd_qtd_t* p_qtd = &_dcd_data.qtd[epnum][dir];
+
+  // Prepare qtd
+  qtd_init(p_qtd, buffer, total_bytes);
+
+  // Start qhd transfer
+  p_qhd->ff = NULL;
+  qhd_start_xfer(rhport, epnum, dir);
+
+  return true;
+}
+
+// fifo has to be aligned to 4k boundary
+bool dcd_edpt_xfer_fifo (uint8_t rhport, uint8_t ep_addr, tu_fifo_t * ff, uint16_t total_bytes)
+{
+  uint8_t const epnum = tu_edpt_number(ep_addr);
+  uint8_t const dir   = tu_edpt_dir(ep_addr);
+
+  dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir];
+  dcd_qtd_t * p_qtd = &_dcd_data.qtd[epnum][dir];
+
+  tu_fifo_buffer_info_t fifo_info;
+
+  if (dir)
+  {
+    tu_fifo_get_read_info(ff, &fifo_info);
+  } else
+  {
+    tu_fifo_get_write_info(ff, &fifo_info);
+  }
+
+  if ( fifo_info.len_lin >= total_bytes )
+  {
+    // Linear length is enough for this transfer
+    qtd_init(p_qtd, fifo_info.ptr_lin, total_bytes);
+  }
+  else
+  {
+    // linear part is not enough
+
+    // prepare TD up to linear length
+    qtd_init(p_qtd, fifo_info.ptr_lin, fifo_info.len_lin);
+
+    if ( !tu_offset4k((uint32_t) fifo_info.ptr_wrap) && !tu_offset4k(tu_fifo_depth(ff)) )
+    {
+      // If buffer is aligned to 4K & buffer size is multiple of 4K
+      // We can make use of buffer page array to also combine the linear + wrapped length
+      p_qtd->total_bytes = p_qtd->expected_bytes = total_bytes;
+
+      for(uint8_t i = 1, page = 0; i < 5; i++)
+      {
+        // pick up buffer array where linear ends
+        if (p_qtd->buffer[i] == 0)
+        {
+          p_qtd->buffer[i] = (uint32_t) fifo_info.ptr_wrap + 4096 * page;
+          page++;
+        }
+      }
+
+      CleanInvalidateDCache_by_Addr((uint32_t*) tu_align((uint32_t) fifo_info.ptr_wrap, 4), total_bytes - fifo_info.len_wrap + 31);
+    }
+    else
+    {
+      // TODO we may need to carry the wrapped length after the linear part complete
+      // for now only transfer up to linear part
+    }
+  }
+
+  // Start qhd transfer
+  p_qhd->ff = ff;
+  qhd_start_xfer(rhport, epnum, dir);
+
+  return true;
+}
+
+//--------------------------------------------------------------------+
+// ISR
+//--------------------------------------------------------------------+
+
+static void process_edpt_complete_isr(uint8_t rhport, uint8_t epnum, uint8_t dir)
+{
+  dcd_qhd_t * p_qhd = &_dcd_data.qhd[epnum][dir];
+  dcd_qtd_t * p_qtd = &_dcd_data.qtd[epnum][dir];
+
+  uint8_t result = p_qtd->halted ? XFER_RESULT_STALLED :
+      ( p_qtd->xact_err || p_qtd->buffer_err ) ? XFER_RESULT_FAILED : XFER_RESULT_SUCCESS;
+
+  if ( result != XFER_RESULT_SUCCESS )
+  {
+    ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
+    // flush to abort error buffer
+    dcd_reg->ENDPTFLUSH = TU_BIT(epnum + (dir ? 16 : 0));
+  }
+
+  uint16_t const xferred_bytes = p_qtd->expected_bytes - p_qtd->total_bytes;
+
+  if (p_qhd->ff)
+  {
+    if (dir == TUSB_DIR_IN)
+    {
+      tu_fifo_advance_read_pointer(p_qhd->ff, xferred_bytes);
+    } else
+    {
+      tu_fifo_advance_write_pointer(p_qhd->ff, xferred_bytes);
+    }
+  }
+  
+  // only number of bytes in the IOC qtd
+  dcd_event_xfer_complete(rhport, tu_edpt_addr(epnum, dir), xferred_bytes, result, true);
+}
+
+void dcd_int_handler(uint8_t rhport)
+{
+  ci_hs_regs_t* dcd_reg = CI_HS_REG(rhport);
+
+  uint32_t const int_enable = dcd_reg->USBINTR;
+  uint32_t const int_status = dcd_reg->USBSTS & int_enable;
+  dcd_reg->USBSTS = int_status; // Acknowledge handled interrupt
+
+  // disabled interrupt sources
+  if (int_status == 0) return;
+
+  // Set if the port controller enters the full or high-speed operational state.
+  // either from Bus Reset or Suspended state
+	if (int_status & INTR_PORT_CHANGE)
+	{
+	  // TU_LOG2("PortChange %08lx\r\n", dcd_reg->PORTSC1);
+
+	  // Reset interrupt is not enabled, we manually check if Port Change is due
+	  // to connection / disconnection
+	  if ( dcd_reg->USBSTS & INTR_RESET )
+	  {
+	    dcd_reg->USBSTS = INTR_RESET;
+
+	    if (dcd_reg->PORTSC1 & PORTSC1_CURRENT_CONNECT_STATUS)
+	    {
+	      uint32_t const speed = (dcd_reg->PORTSC1 & PORTSC1_PORT_SPEED) >> PORTSC1_PORT_SPEED_POS;
+	      bus_reset(rhport);
+	      dcd_event_bus_reset(rhport, (tusb_speed_t) speed, true);
+	    }else
+	    {
+	      dcd_event_bus_signal(rhport, DCD_EVENT_UNPLUGGED, true);
+	    }
+	  }
+	  else
+	  {
+	    // Triggered by resuming from suspended state
+	    if ( !(dcd_reg->PORTSC1 & PORTSC1_SUSPEND) )
+	    {
+	      dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true);
+	    }
+	  }
+	}
+
+  if (int_status & INTR_SUSPEND)
+  {
+    // TU_LOG2("Suspend %08lx\r\n", dcd_reg->PORTSC1);
+
+    if (dcd_reg->PORTSC1 & PORTSC1_SUSPEND)
+    {
+      // Note: Host may delay more than 3 ms before and/or after bus reset before doing enumeration.
+      // Skip suspend event if we are not addressed
+      if ((dcd_reg->DEVICEADDR >> 25) & 0x0f)
+      {
+        dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true);
+      }
+    }
+  }
+
+  if (int_status & INTR_USB)
+  {
+    // Make sure we read the latest version of _dcd_data.
+    CleanInvalidateDCache_by_Addr((uint32_t*) &_dcd_data, sizeof(dcd_data_t));
+
+    uint32_t const edpt_complete = dcd_reg->ENDPTCOMPLETE;
+    dcd_reg->ENDPTCOMPLETE = edpt_complete; // acknowledge
+
+    if (dcd_reg->ENDPTSETUPSTAT)
+    {
+      //------------- Set up Received -------------//
+      // 23.10.10.2 Operational model for setup transfers
+      dcd_reg->ENDPTSETUPSTAT = dcd_reg->ENDPTSETUPSTAT;
+
+      dcd_event_setup_received(rhport, (uint8_t*)(uintptr_t) &_dcd_data.qhd[0][0].setup_request, true);
+    }
+
+    // 23.10.12.3 Failed QTD also get ENDPTCOMPLETE set
+    // nothing to do, we will submit xfer as error to usbd
+    // if (int_status & INTR_ERROR) { }
+
+    if ( edpt_complete )
+    {
+      for(uint8_t epnum = 0; epnum < DCD_ATTR_ENDPOINT_MAX; epnum++)
+      {
+        if ( tu_bit_test(edpt_complete, epnum)    ) process_edpt_complete_isr(rhport, epnum, TUSB_DIR_OUT);
+        if ( tu_bit_test(edpt_complete, epnum+16) ) process_edpt_complete_isr(rhport, epnum, TUSB_DIR_IN);
+      }
+    }
+  }
+
+  if (int_status & INTR_SOF)
+  {
+    dcd_event_bus_signal(rhport, DCD_EVENT_SOF, true);
+  }
+}
+
+#endif

+ 93 - 0
src/portable/chipidea/ci_hs/hcd_ci_hs.c

@@ -0,0 +1,93 @@
+/* 
+ * 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"
+
+// Chipidea Highspeed USB IP implement EHCI for host functionality
+
+#if TUSB_OPT_HOST_ENABLED && \
+    (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX)
+
+//--------------------------------------------------------------------+
+// INCLUDE
+//--------------------------------------------------------------------+
+#include "common/tusb_common.h"
+#include "portable/ehci/ehci_api.h"
+#include "ci_hs_type.h"
+
+#if CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX
+  #include "ci_hs_imxrt.h"
+#elif TU_CHECK_MCU(OPT_MCU_LPC18XX, OPT_MCU_LPC43XX)
+  #include "ci_hs_lpc18_43.h"
+#else
+  #error "Unsupported MCUs"
+#endif
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF
+//--------------------------------------------------------------------+
+
+#define CI_HS_REG(_port)      ((ci_hs_regs_t*) _ci_controller[_port].reg_base)
+
+//--------------------------------------------------------------------+
+// Controller API
+//--------------------------------------------------------------------+
+
+bool hcd_init(uint8_t rhport)
+{
+  ci_hs_regs_t* hcd_reg = CI_HS_REG(rhport);
+
+  // Reset controller
+  hcd_reg->USBCMD |= USBCMD_RESET;
+  while( hcd_reg->USBCMD & USBCMD_RESET ) {}
+
+  // Set mode to device, must be set immediately after reset
+#if CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX
+  // LPC18XX/43XX need to set VBUS Power Select to HIGH
+  // RHPORT1 is fullspeed only (need external PHY for Highspeed)
+  hcd_reg->USBMODE = USBMODE_CM_HOST | USBMODE_VBUS_POWER_SELECT;
+  if (rhport == 1) hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
+#else
+  hcd_reg->USBMODE = USBMODE_CM_HOST;
+#endif
+
+  // FIXME force full speed, still have issue with Highspeed enumeration
+  hcd_reg->PORTSC1 |= PORTSC1_FORCE_FULL_SPEED;
+
+  return ehci_init(rhport, (uint32_t) &hcd_reg->CAPLENGTH, (uint32_t) &hcd_reg->USBCMD);
+}
+
+void hcd_int_enable(uint8_t rhport)
+{
+  CI_HCD_INT_ENABLE(rhport);
+}
+
+void hcd_int_disable(uint8_t rhport)
+{
+  CI_HCD_INT_DISABLE(rhport);
+}
+
+#endif

+ 2 - 0
src/portable/nxp/transdimension/dcd_transdimension.c

@@ -29,6 +29,8 @@
 #if TUSB_OPT_DEVICE_ENABLED && \
     (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX)
 
+#warning "transdimenion is renamed to chipidea (portable/chipidea/ci_hs) to match other opensource naming convention such as linux. This file will be removed in the future, please update your makefile accordingly"
+
 //--------------------------------------------------------------------+
 // INCLUDE
 //--------------------------------------------------------------------+

+ 2 - 0
src/portable/nxp/transdimension/hcd_transdimension.c

@@ -31,6 +31,8 @@
 #if TUSB_OPT_HOST_ENABLED && \
     (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX)
 
+#warning "transdimenion is renamed to chipidea (portable/chipidea/ci_hs) to match other opensource naming convention such as linux. This file will be removed in the future, please update your makefile accordingly"
+
 //--------------------------------------------------------------------+
 // INCLUDE
 //--------------------------------------------------------------------+

+ 21 - 3
src/portable/raspberrypi/rp2040/hcd_rp2040.c

@@ -412,10 +412,28 @@ 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) rhport;
-    (void) dev_addr;
+  pico_trace("hcd_device_close %d\n", dev_addr);
+  (void) rhport;
+
+  if (dev_addr == 0) return;
+
+  for (size_t i = 1; i < TU_ARRAY_SIZE(ep_pool); i++)
+  {
+    hw_endpoint_t* ep = &ep_pool[i];
 
-    pico_trace("hcd_device_close %d\n", dev_addr);
+    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);
+    }
+  }
 }
 
 uint32_t hcd_frame_number(uint8_t rhport)