diff --git a/README.rst b/README.rst
index 6a6f07825..da1f49fcd 100644
--- a/README.rst
+++ b/README.rst
@@ -129,138 +129,134 @@ TinyUSB is completely thread-safe by pushing all Interrupt Service Request (ISR)
Supported CPUs
--------------
-+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+
-| Manufacturer | Family | Device | Host | Highspeed | Driver | Note |
-+==============+=============================+========+======+===========+========================+===================+
-| Allwinner | F1C100s/F1C200s | ✔ | | ✔ | sunxi | musb variant |
-+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+
-| Analog | MAX3421E | | ✔ | ✖ | max3421 | via SPI |
-| +-----------------------------+--------+------+-----------+------------------------+-------------------+
-| | MAX32 650, 666, 690, | ✔ | | ✔ | musb | 1-dir ep |
-| | MAX78002 | | | | | |
-+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+
-| Artery AT32 | F403a_407, F413 | ✔ | | | fsdev | |
-| +-----------------------------+--------+------+-----------+------------------------+-------------------+
-| | F415, F435_437, F423, F425 | ✔ | ✔ | | dwc2 | |
-| +-----------------------------+--------+------+-----------+------------------------+-------------------+
-| | F402_F405 | ✔ | ✔ | ✔ | dwc2 | F405 is HS |
-+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+
-| Bridgetek | FT90x | ✔ | | ✔ | ft9xx | 1-dir ep |
-+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+
-| Broadcom | BCM2711, BCM2837 | ✔ | | ✔ | dwc2 | |
-+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+
-| Dialog | DA1469x | ✔ | ✖ | ✖ | da146xx | |
-+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+
-| Espressif | S2, S3 | ✔ | ✔ | ✖ | dwc2 | |
-| ESP32 +-----------------------------+--------+------+-----------+------------------------+-------------------+
-| | P4 | ✔ | ✔ | ✔ | dwc2 | |
-| +-----------------------------+--------+------+-----------+------------------------+-------------------+
-| | H4 | ✔ | ✔ | ✖ | dwc2 | |
-+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+
-| GigaDevice | GD32VF103 | ✔ | | ✖ | dwc2 | |
-+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+
-| Infineon | XMC4500 | ✔ | ✔ | ✖ | dwc2 | |
-+--------------+-----+-----------------------+--------+------+-----------+------------------------+-------------------+
-| MicroChip | SAM | D11, D21, L21, L22 | ✔ | | ✖ | samd | |
-| | +-----------------------+--------+------+-----------+------------------------+-------------------+
-| | | D51, E5x | ✔ | | ✖ | samd | |
-| | +-----------------------+--------+------+-----------+------------------------+-------------------+
-| | | G55 | ✔ | | ✖ | samg | 1-dir ep |
-| | +-----------------------+--------+------+-----------+------------------------+-------------------+
-| | | E70,S70,V70,V71 | ✔ | | ✔ | samx7x | 1-dir ep |
-| +-----+-----------------------+--------+------+-----------+------------------------+-------------------+
-| | PIC | 24 | ✔ | | | pic | ci_fs variant |
-| | +-----------------------+--------+------+-----------+------------------------+-------------------+
-| | | 32 mm, mk, mx | ✔ | | | pic | ci_fs variant |
-| | +-----------------------+--------+------+-----------+------------------------+-------------------+
-| | | dsPIC33 | ✔ | | | pic | ci_fs variant |
-| | +-----------------------+--------+------+-----------+------------------------+-------------------+
-| | | 32mz | ✔ | | | pic32mz | musb variant |
-+--------------+-----+-----------------------+--------+------+-----------+------------------------+-------------------+
-| MindMotion | mm32 | ✔ | | ✖ | mm32f327x_otg | ci_fs variant |
-+--------------+-----+-----------------------+--------+------+-----------+------------------------+-------------------+
-| NordicSemi | nRF 52833, 52840, 5340 | ✔ | ✖ | ✖ | nrf5x | only ep8 is ISO |
-+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+
-| Nuvoton | NUC120 | ✔ | ✖ | ✖ | nuc120 | |
-| +-----------------------------+--------+------+-----------+------------------------+-------------------+
-| | NUC121/NUC125 | ✔ | ✖ | ✖ | nuc121 | |
-| +-----------------------------+--------+------+-----------+------------------------+-------------------+
-| | NUC126 | ✔ | ✖ | ✖ | nuc121 | |
-| +-----------------------------+--------+------+-----------+------------------------+-------------------+
-| | NUC505 | ✔ | | ✔ | nuc505 | |
-+--------------+---------+-------------------+--------+------+-----------+------------------------+-------------------+
-| NXP | iMXRT | RT 10xx, 11xx | ✔ | ✔ | ✔ | ci_hs, ehci | |
-| +---------+-------------------+--------+------+-----------+------------------------+-------------------+
-| | Kinetis | KL | ✔ | ⚠ | ✖ | ci_fs, khci | |
-| | +-------------------+--------+------+-----------+------------------------+-------------------+
-| | | K32L2 | ✔ | | ✖ | khci | ci_fs variant |
-| +---------+-------------------+--------+------+-----------+------------------------+-------------------+
-| | LPC | 11u, 13, 15 | ✔ | ✖ | ✖ | lpc_ip3511 | |
-| | +-------------------+--------+------+-----------+------------------------+-------------------+
-| | | 17, 40 | ✔ | ⚠ | ✖ | lpc17_40, ohci | |
-| | +-------------------+--------+------+-----------+------------------------+-------------------+
-| | | 18, 43 | ✔ | ✔ | ✔ | ci_hs, ehci | |
-| | +-------------------+--------+------+-----------+------------------------+-------------------+
-| | | 51u | ✔ | ✖ | ✖ | lpc_ip3511 | |
-| | +-------------------+--------+------+-----------+------------------------+-------------------+
-| | | 54, 55 | ✔ | | ✔ | lpc_ip3511 | |
-| +---------+-------------------+--------+------+-----------+------------------------+-------------------+
-| | MCX | N9 | ✔ | | ✔ | ci_fs, ci_hs, ehci | |
-| | +-------------------+--------+------+-----------+------------------------+-------------------+
-| | | A15 | ✔ | | | ci_fs | |
-+--------------+---------+-------------------+--------+------+-----------+------------------------+-------------------+
-| Raspberry Pi | RP2040, RP2350 | ✔ | ✔ | ✖ | rp2040, pio_usb | |
-+--------------+-----+-----------------------+--------+------+-----------+------------------------+-------------------+
-| Renesas | RX | 63N, 65N, 72N | ✔ | ✔ | ✖ | rusb2 | |
-| +-----+-----------------------+--------+------+-----------+------------------------+-------------------+
-| | RA | 4M1, 4M3, 6M1 | ✔ | ✔ | ✖ | rusb2 | |
-| | +-----------------------+--------+------+-----------+------------------------+-------------------+
-| | | 6M5 | ✔ | ✔ | ✔ | rusb2 | |
-+--------------+-----+-----------------------+--------+------+-----------+------------------------+-------------------+
-| Silabs | EFM32GG12 | ✔ | | ✖ | dwc2 | |
-+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+
-| Sony | CXD56 | ✔ | ✖ | ✔ | cxd56 | |
-+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+
-| ST STM32 | F0, F3, L0, L1, L5, WBx5 | ✔ | ✖ | ✖ | stm32_fsdev | |
-| +----+------------------------+--------+------+-----------+------------------------+-------------------+
-| | F1 | 102, 103 | ✔ | ✖ | ✖ | stm32_fsdev | |
-| | +------------------------+--------+------+-----------+------------------------+-------------------+
-| | | 105, 107 | ✔ | ✔ | ✖ | dwc2 | |
-| +----+------------------------+--------+------+-----------+------------------------+-------------------+
-| | F2, F4, F7, H7, H7RS | ✔ | ✔ | ✔ | dwc2 | |
-| +-----------------------------+--------+------+-----------+------------------------+-------------------+
-| | C0, G0, H5 | ✔ | | ✖ | stm32_fsdev | |
-| +-----------------------------+--------+------+-----------+------------------------+-------------------+
-| | G4 | ✔ | ✖ | ✖ | stm32_fsdev | |
-| +----+------------------------+--------+------+-----------+------------------------+-------------------+
-| | L4 | 4x2, 4x3 | ✔ | ✖ | ✖ | stm32_fsdev | |
-| | +------------------------+--------+------+-----------+------------------------+-------------------+
-| | | 4x5, 4x6, 4+ | ✔ | ✔ | ✖ | dwc2 | |
-| +----+------------------------+--------+------+-----------+------------------------+-------------------+
-| | N6 | ✔ | ✔ | ✔ | dwc2 | |
-| +----+------------------------+--------+------+-----------+------------------------+-------------------+
-| | U0 | ✔ | ✖ | ✖ | stm32_fsdev | |
-| +----+------------------------+--------+------+-----------+------------------------+-------------------+
-| | U3 | ✔ | | ✖ | stm32_fsdev | |
-| +----+------------------------+--------+------+-----------+------------------------+-------------------+
-| | U5 | 535, 545 | ✔ | | ✖ | stm32_fsdev | |
-| | +------------------------+--------+------+-----------+------------------------+-------------------+
-| | | 575, 585 | ✔ | ✔ | ✖ | dwc2 | |
-| | +------------------------+--------+------+-----------+------------------------+-------------------+
-| | | 59x,5Ax,5Fx,5Gx | ✔ | ✔ | ✔ | dwc2 | |
-+--------------+----+------------------------+--------+------+-----------+------------------------+-------------------+
-| TI | MSP430 | ✔ | ✖ | ✖ | msp430x5xx | |
-| +-----------------------------+--------+------+-----------+------------------------+-------------------+
-| | MSP432E4, TM4C123 | ✔ | | ✖ | musb | |
-+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+
-| ValentyUSB | eptri | ✔ | ✖ | ✖ | eptri | |
-+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+
-| WCH | CH32F20x | ✔ | | ✔ | ch32_usbhs | |
-| +-----------------------------+--------+------+-----------+------------------------+-------------------+
-| | CH32V20x | ✔ | | ✖ | stm32_fsdev/ch32_usbfs | |
-| +-----------------------------+--------+------+-----------+------------------------+-------------------+
-| | CH32V305, CH32V307 | ✔ | | ✔ | ch32_usbfs/hs | |
-+--------------+-----------------------------+--------+------+-----------+------------------------+-------------------+
++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+
+| Manufacturer | Family | Device | Host | Highspeed | Driver | Note |
++==============+=============================+========+======+===========+========================+====================+
+| Allwinner | F1C100s/F1C200s | ✔ | | ✔ | sunxi | musb variant |
++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+
+| Analog | MAX3421E | | ✔ | ✖ | max3421 | via SPI |
+| +-----------------------------+--------+------+-----------+------------------------+--------------------+
+| | MAX32 650, 666, 690, | ✔ | | ✔ | musb | 1-dir ep |
+| | MAX78002 | | | | | |
++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+
+| Artery AT32 | F403a_407, F413 | ✔ | | | fsdev | Packet SRAM 512 |
+| +-----------------------------+--------+------+-----------+------------------------+--------------------+
+| | F415, F435_437, F423, F425 | ✔ | ✔ | | dwc2 | |
+| +-----------------------------+--------+------+-----------+------------------------+--------------------+
+| | F402_F405 | ✔ | ✔ | ✔ | dwc2 | F405 is HS |
++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+
+| Bridgetek | FT90x | ✔ | | ✔ | ft9xx | 1-dir ep |
++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+
+| Broadcom | BCM2711, BCM2837 | ✔ | | ✔ | dwc2 | |
++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+
+| Dialog | DA1469x | ✔ | ✖ | ✖ | da146xx | |
++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+
+| Espressif | S2, S3 | ✔ | ✔ | ✖ | dwc2 | |
+| ESP32 +-----------------------------+--------+------+-----------+------------------------+--------------------+
+| | P4 | ✔ | ✔ | ✔ | dwc2 | |
+| +-----------------------------+--------+------+-----------+------------------------+--------------------+
+| | H4 | ✔ | ✔ | ✖ | dwc2 | |
++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+
+| GigaDevice | GD32VF103 | ✔ | | ✖ | dwc2 | |
++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+
+| Infineon | XMC4500 | ✔ | ✔ | ✖ | dwc2 | |
++--------------+-----+-----------------------+--------+------+-----------+------------------------+--------------------+
+| MicroChip | SAM | D11, D21, L21, L22 | ✔ | | ✖ | samd | |
+| | +-----------------------+--------+------+-----------+------------------------+--------------------+
+| | | D51, E5x | ✔ | | ✖ | samd | |
+| | +-----------------------+--------+------+-----------+------------------------+--------------------+
+| | | G55 | ✔ | | ✖ | samg | 1-dir ep |
+| | +-----------------------+--------+------+-----------+------------------------+--------------------+
+| | | E70,S70,V70,V71 | ✔ | | ✔ | samx7x | 1-dir ep |
+| +-----+-----------------------+--------+------+-----------+------------------------+--------------------+
+| | PIC | 24 | ✔ | | | pic | ci_fs variant |
+| | +-----------------------+--------+------+-----------+------------------------+--------------------+
+| | | 32 mm, mk, mx | ✔ | | | pic | ci_fs variant |
+| | +-----------------------+--------+------+-----------+------------------------+--------------------+
+| | | dsPIC33 | ✔ | | | pic | ci_fs variant |
+| | +-----------------------+--------+------+-----------+------------------------+--------------------+
+| | | 32mz | ✔ | | | pic32mz | musb variant |
++--------------+-----+-----------------------+--------+------+-----------+------------------------+--------------------+
+| MindMotion | mm32 | ✔ | | ✖ | mm32f327x_otg | ci_fs variant |
++--------------+-----+-----------------------+--------+------+-----------+------------------------+--------------------+
+| NordicSemi | nRF 52833, 52840, 5340 | ✔ | ✖ | ✖ | nrf5x | only ep8 is ISO |
++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+
+| Nuvoton | NUC120 | ✔ | ✖ | ✖ | nuc120 | |
+| +-----------------------------+--------+------+-----------+------------------------+--------------------+
+| | NUC121/NUC125, NUC126 | ✔ | ✖ | ✖ | nuc121 | |
+| +-----------------------------+--------+------+-----------+------------------------+--------------------+
+| | NUC505 | ✔ | | ✔ | nuc505 | |
++--------------+---------+-------------------+--------+------+-----------+------------------------+--------------------+
+| NXP | iMXRT | RT 10xx, 11xx | ✔ | ✔ | ✔ | ci_hs, ehci | |
+| +---------+-------------------+--------+------+-----------+------------------------+--------------------+
+| | Kinetis | KL | ✔ | ⚠ | ✖ | ci_fs, khci | |
+| | +-------------------+--------+------+-----------+------------------------+--------------------+
+| | | K32L2 | ✔ | | ✖ | khci | ci_fs variant |
+| +---------+-------------------+--------+------+-----------+------------------------+--------------------+
+| | LPC | 11u, 13, 15 | ✔ | ✖ | ✖ | lpc_ip3511 | |
+| | +-------------------+--------+------+-----------+------------------------+--------------------+
+| | | 17, 40 | ✔ | ⚠ | ✖ | lpc17_40, ohci | |
+| | +-------------------+--------+------+-----------+------------------------+--------------------+
+| | | 18, 43 | ✔ | ✔ | ✔ | ci_hs, ehci | |
+| | +-------------------+--------+------+-----------+------------------------+--------------------+
+| | | 51u | ✔ | ✖ | ✖ | lpc_ip3511 | |
+| | +-------------------+--------+------+-----------+------------------------+--------------------+
+| | | 54, 55 | ✔ | | ✔ | lpc_ip3511 | |
+| +---------+-------------------+--------+------+-----------+------------------------+--------------------+
+| | MCX | N9 | ✔ | | ✔ | ci_fs, ci_hs, ehci | |
+| | +-------------------+--------+------+-----------+------------------------+--------------------+
+| | | A15 | ✔ | | | ci_fs | |
++--------------+---------+-------------------+--------+------+-----------+------------------------+--------------------+
+| Raspberry Pi | RP2040, RP2350 | ✔ | ✔ | ✖ | rp2040, pio_usb | |
++--------------+-----+-----------------------+--------+------+-----------+------------------------+--------------------+
+| Renesas | RX | 63N, 65N, 72N | ✔ | ✔ | ✖ | rusb2 | |
+| +-----+-----------------------+--------+------+-----------+------------------------+--------------------+
+| | RA | 4M1, 4M3, 6M1 | ✔ | ✔ | ✖ | rusb2 | |
+| | +-----------------------+--------+------+-----------+------------------------+--------------------+
+| | | 6M5 | ✔ | ✔ | ✔ | rusb2 | |
++--------------+-----+-----------------------+--------+------+-----------+------------------------+--------------------+
+| Silabs | EFM32GG12 | ✔ | | ✖ | dwc2 | |
++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+
+| Sony | CXD56 | ✔ | ✖ | ✔ | cxd56 | |
++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+
+| ST STM32 | F0, F3, L0, L1, L5, WBx5 | ✔ | ✖ | ✖ | stm32_fsdev | |
+| +----+------------------------+--------+------+-----------+------------------------+--------------------+
+| | F1 | 102, 103 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 512 |
+| | +------------------------+--------+------+-----------+------------------------+--------------------+
+| | | 105, 107 | ✔ | ✔ | ✖ | dwc2 | |
+| +----+------------------------+--------+------+-----------+------------------------+--------------------+
+| | F2, F4, F7, H7, H7RS | ✔ | ✔ | ✔ | dwc2 | |
+| +-----------------------------+--------+------+-----------+------------------------+--------------------+
+| | C0, G0, H5, U3 | ✔ | ✔ | ✖ | stm32_fsdev | Packet SRAM 2KB |
+| +-----------------------------+--------+------+-----------+------------------------+--------------------+
+| | G4 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 1KB |
+| +----+------------------------+--------+------+-----------+------------------------+--------------------+
+| | L4 | 4x2, 4x3 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 1KB |
+| | +------------------------+--------+------+-----------+------------------------+--------------------+
+| | | 4x5, 4x6, 4+ | ✔ | ✔ | ✖ | dwc2 | |
+| +----+------------------------+--------+------+-----------+------------------------+--------------------+
+| | N6 | ✔ | ✔ | ✔ | dwc2 | |
+| +-----------------------------+--------+------+-----------+------------------------+--------------------+
+| | U0 | ✔ | ✖ | ✖ | stm32_fsdev | Packet SRAM 1KB |
+| +----+------------------------+--------+------+-----------+------------------------+--------------------+
+| | U5 | 535, 545 | ✔ | ✔ | ✖ | stm32_fsdev | Packet SRAM 2KB |
+| | +------------------------+--------+------+-----------+------------------------+--------------------+
+| | | 575, 585 | ✔ | ✔ | ✖ | dwc2 | |
+| | +------------------------+--------+------+-----------+------------------------+--------------------+
+| | | 59x,5Ax,5Fx,5Gx | ✔ | ✔ | ✔ | dwc2 | |
++--------------+----+------------------------+--------+------+-----------+------------------------+--------------------+
+| TI | MSP430 | ✔ | ✖ | ✖ | msp430x5xx | |
+| +-----------------------------+--------+------+-----------+------------------------+--------------------+
+| | MSP432E4, TM4C123 | ✔ | | ✖ | musb | |
++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+
+| ValentyUSB | eptri | ✔ | ✖ | ✖ | eptri | |
++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+
+| WCH | CH32F20x | ✔ | | ✔ | ch32_usbhs | |
+| +-----------------------------+--------+------+-----------+------------------------+--------------------+
+| | CH32V20x | ✔ | | ✖ | stm32_fsdev/ch32_usbfs | |
+| +-----------------------------+--------+------+-----------+------------------------+--------------------+
+| | CH32V305, CH32V307 | ✔ | | ✔ | ch32_usbfs/hs | |
++--------------+-----------------------------+--------+------+-----------+------------------------+--------------------+
Table Legend
^^^^^^^^^^^^
diff --git a/examples/host/bare_api/only.txt b/examples/host/bare_api/only.txt
index cba58f8e8..52e51242c 100644
--- a/examples/host/bare_api/only.txt
+++ b/examples/host/bare_api/only.txt
@@ -1,3 +1,5 @@
+family:samd21
+family:samd5x_e5x
mcu:CH32V20X
mcu:KINETIS_KL
mcu:LPC175X_6X
@@ -5,18 +7,21 @@ mcu:LPC177X_8X
mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
-mcu:MIMXRT1XXX
+mcu:MAX3421
mcu:MIMXRT10XX
mcu:MIMXRT11XX
-mcu:RP2040
+mcu:MIMXRT1XXX
mcu:MSP432E4
-mcu:RX65X
mcu:RAXXX
-mcu:MAX3421
+mcu:RP2040
+mcu:RX65X
+mcu:STM32C0
mcu:STM32F4
mcu:STM32F7
+mcu:STM32G0
+mcu:STM32H5
mcu:STM32H7
mcu:STM32H7RS
mcu:STM32N6
-family:samd21
-family:samd5x_e5x
+mcu:STM32U3
+mcu:STM32U5
diff --git a/examples/host/cdc_msc_hid/only.txt b/examples/host/cdc_msc_hid/only.txt
index cba58f8e8..52e51242c 100644
--- a/examples/host/cdc_msc_hid/only.txt
+++ b/examples/host/cdc_msc_hid/only.txt
@@ -1,3 +1,5 @@
+family:samd21
+family:samd5x_e5x
mcu:CH32V20X
mcu:KINETIS_KL
mcu:LPC175X_6X
@@ -5,18 +7,21 @@ mcu:LPC177X_8X
mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
-mcu:MIMXRT1XXX
+mcu:MAX3421
mcu:MIMXRT10XX
mcu:MIMXRT11XX
-mcu:RP2040
+mcu:MIMXRT1XXX
mcu:MSP432E4
-mcu:RX65X
mcu:RAXXX
-mcu:MAX3421
+mcu:RP2040
+mcu:RX65X
+mcu:STM32C0
mcu:STM32F4
mcu:STM32F7
+mcu:STM32G0
+mcu:STM32H5
mcu:STM32H7
mcu:STM32H7RS
mcu:STM32N6
-family:samd21
-family:samd5x_e5x
+mcu:STM32U3
+mcu:STM32U5
diff --git a/examples/host/cdc_msc_hid_freertos/only.txt b/examples/host/cdc_msc_hid_freertos/only.txt
index ef0a1ac96..4cff741c3 100644
--- a/examples/host/cdc_msc_hid_freertos/only.txt
+++ b/examples/host/cdc_msc_hid_freertos/only.txt
@@ -1,19 +1,24 @@
+family:espressif
+family:samd21
+family:samd5x_e5x
mcu:LPC175X_6X
mcu:LPC177X_8X
mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
-mcu:MIMXRT1XXX
+mcu:MAX3421
mcu:MIMXRT10XX
mcu:MIMXRT11XX
+mcu:MIMXRT1XXX
mcu:MSP432E4
mcu:RX65X
-mcu:MAX3421
+mcu:STM32C0
mcu:STM32F4
mcu:STM32F7
+mcu:STM32G0
+mcu:STM32H5
mcu:STM32H7
mcu:STM32H7RS
mcu:STM32N6
-family:espressif
-family:samd21
-family:samd5x_e5x
+mcu:STM32U3
+mcu:STM32U5
diff --git a/examples/host/device_info/only.txt b/examples/host/device_info/only.txt
index 61a08f68d..becc8252d 100644
--- a/examples/host/device_info/only.txt
+++ b/examples/host/device_info/only.txt
@@ -1,3 +1,6 @@
+family:espressif
+family:samd21
+family:samd5x_e5x
mcu:CH32V20X
mcu:KINETIS_KL
mcu:LPC175X_6X
@@ -6,18 +9,20 @@ mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
mcu:MAX3421
-mcu:MIMXRT1XXX
mcu:MIMXRT10XX
mcu:MIMXRT11XX
+mcu:MIMXRT1XXX
mcu:MSP432E4
+mcu:RAXXX
mcu:RP2040
mcu:RX65X
-mcu:RAXXX
+mcu:STM32C0
mcu:STM32F4
mcu:STM32F7
+mcu:STM32G0
+mcu:STM32H5
mcu:STM32H7
mcu:STM32H7RS
mcu:STM32N6
-family:espressif
-family:samd21
-family:samd5x_e5x
+mcu:STM32U3
+mcu:STM32U5
diff --git a/examples/host/hid_controller/only.txt b/examples/host/hid_controller/only.txt
index cba58f8e8..35b7c2361 100644
--- a/examples/host/hid_controller/only.txt
+++ b/examples/host/hid_controller/only.txt
@@ -1,3 +1,5 @@
+family:samd21
+family:samd5x_e5x
mcu:CH32V20X
mcu:KINETIS_KL
mcu:LPC175X_6X
@@ -5,18 +7,20 @@ mcu:LPC177X_8X
mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
-mcu:MIMXRT1XXX
+mcu:MAX3421
mcu:MIMXRT10XX
mcu:MIMXRT11XX
-mcu:RP2040
+mcu:MIMXRT1XXX
mcu:MSP432E4
-mcu:RX65X
mcu:RAXXX
-mcu:MAX3421
+mcu:RP2040
+mcu:RX65X
mcu:STM32F4
mcu:STM32F7
+mcu:STM32G0
+mcu:STM32H5
mcu:STM32H7
mcu:STM32H7RS
mcu:STM32N6
-family:samd21
-family:samd5x_e5x
+mcu:STM32U3
+mcu:STM32U5
diff --git a/examples/host/midi_rx/only.txt b/examples/host/midi_rx/only.txt
index 133a7c9a0..a3976f08d 100644
--- a/examples/host/midi_rx/only.txt
+++ b/examples/host/midi_rx/only.txt
@@ -1,7 +1,9 @@
+family:samd21
+family:samd5x_e5x
mcu:CH32V20X
+mcu:ESP32P4
mcu:ESP32S2
mcu:ESP32S3
-mcu:ESP32P4
mcu:KINETIS_KL
mcu:LPC175X_6X
mcu:LPC177X_8X
@@ -9,17 +11,20 @@ mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
mcu:MAX3421
-mcu:MIMXRT1XXX
mcu:MIMXRT10XX
mcu:MIMXRT11XX
+mcu:MIMXRT1XXX
mcu:MSP432E4
+mcu:RAXXX
mcu:RP2040
mcu:RX65X
-mcu:RAXXX
+mcu:STM32C0
mcu:STM32F4
mcu:STM32F7
+mcu:STM32G0
+mcu:STM32H5
mcu:STM32H7
mcu:STM32H7RS
mcu:STM32N6
-family:samd21
-family:samd5x_e5x
+mcu:STM32U3
+mcu:STM32U5
diff --git a/examples/host/msc_file_explorer/only.txt b/examples/host/msc_file_explorer/only.txt
index cba58f8e8..52e51242c 100644
--- a/examples/host/msc_file_explorer/only.txt
+++ b/examples/host/msc_file_explorer/only.txt
@@ -1,3 +1,5 @@
+family:samd21
+family:samd5x_e5x
mcu:CH32V20X
mcu:KINETIS_KL
mcu:LPC175X_6X
@@ -5,18 +7,21 @@ mcu:LPC177X_8X
mcu:LPC18XX
mcu:LPC40XX
mcu:LPC43XX
-mcu:MIMXRT1XXX
+mcu:MAX3421
mcu:MIMXRT10XX
mcu:MIMXRT11XX
-mcu:RP2040
+mcu:MIMXRT1XXX
mcu:MSP432E4
-mcu:RX65X
mcu:RAXXX
-mcu:MAX3421
+mcu:RP2040
+mcu:RX65X
+mcu:STM32C0
mcu:STM32F4
mcu:STM32F7
+mcu:STM32G0
+mcu:STM32H5
mcu:STM32H7
mcu:STM32H7RS
mcu:STM32N6
-family:samd21
-family:samd5x_e5x
+mcu:STM32U3
+mcu:STM32U5
diff --git a/hw/bsp/at32f403a_407/family.cmake b/hw/bsp/at32f403a_407/family.cmake
index 498b89c1a..7aaa9ede8 100644
--- a/hw/bsp/at32f403a_407/family.cmake
+++ b/hw/bsp/at32f403a_407/family.cmake
@@ -61,6 +61,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
diff --git a/hw/bsp/at32f403a_407/family.mk b/hw/bsp/at32f403a_407/family.mk
index c82d402ca..f458881a3 100644
--- a/hw/bsp/at32f403a_407/family.mk
+++ b/hw/bsp/at32f403a_407/family.mk
@@ -16,6 +16,7 @@ LDFLAGS_GCC += \
SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
+ src/portable/st/stm32_fsdev/fsdev_common.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \
diff --git a/hw/bsp/at32f413/family.cmake b/hw/bsp/at32f413/family.cmake
index 02692daf5..33718bd1c 100644
--- a/hw/bsp/at32f413/family.cmake
+++ b/hw/bsp/at32f413/family.cmake
@@ -61,6 +61,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_clock.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/${AT32_FAMILY}_int.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
diff --git a/hw/bsp/at32f413/family.mk b/hw/bsp/at32f413/family.mk
index 9c5d867de..abcd15d11 100644
--- a/hw/bsp/at32f413/family.mk
+++ b/hw/bsp/at32f413/family.mk
@@ -16,6 +16,7 @@ LDFLAGS_GCC += \
SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
+ src/portable/st/stm32_fsdev/fsdev_common.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_gpio.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_misc.c \
$(AT32_SDK_LIB)/drivers/src/${AT32_FAMILY}_usart.c \
diff --git a/hw/bsp/ch32v20x/family.cmake b/hw/bsp/ch32v20x/family.cmake
index d8c7c5327..59a96f70d 100644
--- a/hw/bsp/ch32v20x/family.cmake
+++ b/hw/bsp/ch32v20x/family.cmake
@@ -93,6 +93,7 @@ function(family_configure_example TARGET RTOS)
${TOP}/src/portable/wch/dcd_ch32_usbfs.c
${TOP}/src/portable/wch/hcd_ch32_usbfs.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
diff --git a/hw/bsp/ch32v20x/family.mk b/hw/bsp/ch32v20x/family.mk
index 16fc537ac..7042ecbb7 100644
--- a/hw/bsp/ch32v20x/family.mk
+++ b/hw/bsp/ch32v20x/family.mk
@@ -47,6 +47,7 @@ SRC_C += \
src/portable/wch/dcd_ch32_usbfs.c \
src/portable/wch/hcd_ch32_usbfs.c \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
+ src/portable/st/stm32_fsdev/fsdev_common.c \
$(SDK_SRC_DIR)/Core/core_riscv.c \
$(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_gpio.c \
$(SDK_SRC_DIR)/Peripheral/src/${CH32_FAMILY}_misc.c \
diff --git a/hw/bsp/stm32c0/boards/stm32c071nucleo/STM32C071RBTx_FLASH.ld b/hw/bsp/stm32c0/boards/stm32c071nucleo/STM32C071RBTx_FLASH.ld
index 8acd49f9d..6c7e203f1 100644
--- a/hw/bsp/stm32c0/boards/stm32c071nucleo/STM32C071RBTx_FLASH.ld
+++ b/hw/bsp/stm32c0/boards/stm32c071nucleo/STM32C071RBTx_FLASH.ld
@@ -36,7 +36,7 @@
ENTRY(Reset_Handler)
_Min_Heap_Size = 0x200; /* required amount of heap */
-_Min_Stack_Size = 0x400; /* required amount of stack */
+_Min_Stack_Size = 0xc00; /* required amount of stack */
/* Memories definition */
MEMORY
diff --git a/hw/bsp/stm32c0/boards/stm32c071nucleo/board.cmake b/hw/bsp/stm32c0/boards/stm32c071nucleo/board.cmake
index 2a319a73c..ed70cffbf 100644
--- a/hw/bsp/stm32c0/boards/stm32c071nucleo/board.cmake
+++ b/hw/bsp/stm32c0/boards/stm32c071nucleo/board.cmake
@@ -2,6 +2,7 @@ set(MCU_VARIANT stm32c071xx)
set(JLINK_DEVICE stm32c071rb)
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/STM32C071RBTx_FLASH.ld)
+set(LD_FILE_IAR ${CMAKE_CURRENT_LIST_DIR}/stm32c071xx_flash.icf)
function(update_board TARGET)
target_compile_definitions(${TARGET} PUBLIC
diff --git a/hw/bsp/stm32c0/boards/stm32c071nucleo/board.h b/hw/bsp/stm32c0/boards/stm32c071nucleo/board.h
index 751df2251..460b42a21 100644
--- a/hw/bsp/stm32c0/boards/stm32c071nucleo/board.h
+++ b/hw/bsp/stm32c0/boards/stm32c071nucleo/board.h
@@ -64,36 +64,30 @@
static inline void board_clock_init(void) {
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
- RCC_CRSInitTypeDef RCC_CRSInitStruct = {0};
+ RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};
- /* -1- Enable HSIUSB48 Oscillator */
- RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI48;
- RCC_OscInitStruct.HSI48State = RCC_HSI48_ON;
+ __HAL_FLASH_SET_LATENCY(FLASH_LATENCY_1);
+ /** Initializes the RCC Oscillators according to the specified parameters
+ * in the RCC_OscInitTypeDef structure.
+ */
+ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
+ RCC_OscInitStruct.HSEState = RCC_HSE_ON;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
- /* -2- Initializes the CPU, AHB and APB buses clocks */
+ /** Initializes the CPU, AHB and APB buses clocks
+ */
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1;
- RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSIUSB48;
+ RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE;
RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV1;
HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);
-
- __HAL_RCC_CRS_CLK_ENABLE();
-
- // Configures CRS
- RCC_CRSInitStruct.Prescaler = RCC_CRS_SYNC_DIV1;
- RCC_CRSInitStruct.Source = RCC_CRS_SYNC_SOURCE_USB;
- RCC_CRSInitStruct.Polarity = RCC_CRS_SYNC_POLARITY_RISING;
- RCC_CRSInitStruct.ReloadValue = __HAL_RCC_CRS_RELOADVALUE_CALCULATE(48000000,1000);
- RCC_CRSInitStruct.ErrorLimitValue = 34;
- RCC_CRSInitStruct.HSI48CalibrationValue = 32;
-
- HAL_RCCEx_CRSConfig(&RCC_CRSInitStruct);
+ PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB;
+ PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_HSE;
+ HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
}
-
#endif /* BOARD_H_ */
diff --git a/hw/bsp/stm32c0/boards/stm32c071nucleo/board.mk b/hw/bsp/stm32c0/boards/stm32c071nucleo/board.mk
index 67a9b59a8..fd22fc8d4 100644
--- a/hw/bsp/stm32c0/boards/stm32c071nucleo/board.mk
+++ b/hw/bsp/stm32c0/boards/stm32c071nucleo/board.mk
@@ -7,7 +7,7 @@ LD_FILE_GCC = $(BOARD_PATH)/STM32C071RBTx_FLASH.ld
# IAR
SRC_S_IAR += $(ST_CMSIS)/Source/Templates/iar/startup_stm32c071xx.s
-LD_FILE_IAR = $(ST_CMSIS)/Source/Templates/iar/linker/stm32c071xx_flash.icf
+LD_FILE_IAR = $(BOARD_PATH)/stm32c071xx_flash.icf
# For flash-jlink target
JLINK_DEVICE = stm32c071rb
diff --git a/hw/bsp/stm32c0/boards/stm32c071nucleo/stm32c071xx_flash.icf b/hw/bsp/stm32c0/boards/stm32c071nucleo/stm32c071xx_flash.icf
new file mode 100644
index 000000000..684f41dc6
--- /dev/null
+++ b/hw/bsp/stm32c0/boards/stm32c071nucleo/stm32c071xx_flash.icf
@@ -0,0 +1,33 @@
+/*###ICF### Section handled by ICF editor, don't touch! ****/
+/*-Editor annotation file-*/
+/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
+/*-Specials-*/
+define symbol __ICFEDIT_intvec_start__ = 0x08000000;
+/*-Memory Regions-*/
+define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
+define symbol __ICFEDIT_region_ROM_end__ = 0x0801FFFF;
+define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
+define symbol __ICFEDIT_region_RAM_end__ = 0x20005FFF;
+/*-Sizes-*/
+define symbol __ICFEDIT_size_cstack__ = 0xc00;
+define symbol __ICFEDIT_size_heap__ = 0x200;
+/**** End of ICF editor section. ###ICF###*/
+
+define memory mem with size = 4G;
+define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
+define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
+
+define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
+define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
+
+initialize by copy { readwrite };
+do not initialize { section .noinit };
+
+place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
+
+place in ROM_region { readonly };
+place in RAM_region { readwrite,
+ block CSTACK, block HEAP };
+
+export symbol __ICFEDIT_region_RAM_start__;
+export symbol __ICFEDIT_region_RAM_end__;
diff --git a/hw/bsp/stm32c0/family.c b/hw/bsp/stm32c0/family.c
index ba8b14dd1..e2ba47f45 100644
--- a/hw/bsp/stm32c0/family.c
+++ b/hw/bsp/stm32c0/family.c
@@ -37,13 +37,13 @@
// Forward USB interrupt events to TinyUSB IRQ Handler
//--------------------------------------------------------------------+
void USB_DRD_FS_IRQHandler(void) {
- tud_int_handler(0);
+ tusb_int_handler(0, true);
}
// Startup code generated by STM32CubeIDE uses USB_IRQHandler, while
// stm32c071xx.s from cmsis_device_c0 uses USB_DRD_FS_IRQHandler.
void USB_IRQHandler(void) {
- USB_DRD_FS_IRQHandler();
+ tusb_int_handler(0, true);
}
//--------------------------------------------------------------------+
diff --git a/hw/bsp/stm32c0/family.cmake b/hw/bsp/stm32c0/family.cmake
index 90d5322b7..dc1a2bb13 100644
--- a/hw/bsp/stm32c0/family.cmake
+++ b/hw/bsp/stm32c0/family.cmake
@@ -24,7 +24,6 @@ set(STARTUP_FILE_GNU ${ST_CMSIS}/Source/Templates/gcc/startup_${MCU_VARIANT}.s)
set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s)
set(LD_FILE_Clang ${LD_FILE_GNU})
-set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf)
#------------------------------------
# BOARD_TARGET
@@ -67,6 +66,8 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${TOP}/src/portable/st/typec/typec_stm32.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
diff --git a/hw/bsp/stm32c0/family.mk b/hw/bsp/stm32c0/family.mk
index bdb34454e..71209bf2e 100644
--- a/hw/bsp/stm32c0/family.mk
+++ b/hw/bsp/stm32c0/family.mk
@@ -29,6 +29,8 @@ LDFLAGS_GCC += \
SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
+ src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c \
+ src/portable/st/stm32_fsdev/fsdev_common.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \
diff --git a/hw/bsp/stm32c0/stm32c0xx_hal_conf.h b/hw/bsp/stm32c0/stm32c0xx_hal_conf.h
index 678b6ee0d..874251c7f 100644
--- a/hw/bsp/stm32c0/stm32c0xx_hal_conf.h
+++ b/hw/bsp/stm32c0/stm32c0xx_hal_conf.h
@@ -92,7 +92,7 @@ extern "C" {
* (when HSE is used as system clock source, directly or through the PLL).
*/
#if !defined (HSE_VALUE)
-#define HSE_VALUE (8000000U) /*!< Value of the External oscillator in Hz */
+#define HSE_VALUE (48000000U) /*!< Value of the External oscillator in Hz */
#endif /* HSE_VALUE */
#if !defined (HSE_STARTUP_TIMEOUT)
diff --git a/hw/bsp/stm32f0/family.cmake b/hw/bsp/stm32f0/family.cmake
index ee73ae872..a926a9739 100644
--- a/hw/bsp/stm32f0/family.cmake
+++ b/hw/bsp/stm32f0/family.cmake
@@ -65,6 +65,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
diff --git a/hw/bsp/stm32f0/family.mk b/hw/bsp/stm32f0/family.mk
index 9b8305874..b5efdcb8d 100644
--- a/hw/bsp/stm32f0/family.mk
+++ b/hw/bsp/stm32f0/family.mk
@@ -30,6 +30,7 @@ LDFLAGS_GCC += \
SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
+ src/portable/st/stm32_fsdev/fsdev_common.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \
diff --git a/hw/bsp/stm32f1/family.cmake b/hw/bsp/stm32f1/family.cmake
index 064f32096..9e94d86c6 100644
--- a/hw/bsp/stm32f1/family.cmake
+++ b/hw/bsp/stm32f1/family.cmake
@@ -62,6 +62,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
diff --git a/hw/bsp/stm32f1/family.mk b/hw/bsp/stm32f1/family.mk
index ca95f2315..d4b6dfa6c 100644
--- a/hw/bsp/stm32f1/family.mk
+++ b/hw/bsp/stm32f1/family.mk
@@ -27,6 +27,7 @@ LDFLAGS_GCC += \
# ------------------------
SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
+ src/portable/st/stm32_fsdev/fsdev_common.c \
${ST_CMSIS}/Source/Templates/system_stm32${ST_FAMILY}xx.c \
${ST_HAL_DRIVER}/Src/stm32${ST_FAMILY}xx_hal.c \
${ST_HAL_DRIVER}/Src/stm32${ST_FAMILY}xx_hal_cortex.c \
diff --git a/hw/bsp/stm32f3/family.cmake b/hw/bsp/stm32f3/family.cmake
index 7c9e97e62..3cbb4e1cd 100644
--- a/hw/bsp/stm32f3/family.cmake
+++ b/hw/bsp/stm32f3/family.cmake
@@ -62,6 +62,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
diff --git a/hw/bsp/stm32f3/family.mk b/hw/bsp/stm32f3/family.mk
index 13734583a..eb4a4e186 100644
--- a/hw/bsp/stm32f3/family.mk
+++ b/hw/bsp/stm32f3/family.mk
@@ -19,6 +19,7 @@ LDFLAGS_GCC += \
SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
+ src/portable/st/stm32_fsdev/fsdev_common.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \
diff --git a/hw/bsp/stm32g0/family.c b/hw/bsp/stm32g0/family.c
index 7b86aedb4..4b175b0ec 100644
--- a/hw/bsp/stm32g0/family.c
+++ b/hw/bsp/stm32g0/family.c
@@ -37,7 +37,7 @@
// Forward USB interrupt events to TinyUSB IRQ Handler
//--------------------------------------------------------------------+
void USB_UCPD1_2_IRQHandler(void) {
- tud_int_handler(0);
+ tusb_int_handler(0, true);
}
//--------------------------------------------------------------------+
diff --git a/hw/bsp/stm32g0/family.cmake b/hw/bsp/stm32g0/family.cmake
index 572f0e644..4b520a0e1 100644
--- a/hw/bsp/stm32g0/family.cmake
+++ b/hw/bsp/stm32g0/family.cmake
@@ -64,6 +64,8 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${TOP}/src/portable/st/typec/typec_stm32.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
diff --git a/hw/bsp/stm32g0/family.mk b/hw/bsp/stm32g0/family.mk
index d735ca92d..e376f7f06 100644
--- a/hw/bsp/stm32g0/family.mk
+++ b/hw/bsp/stm32g0/family.mk
@@ -29,6 +29,8 @@ LDFLAGS_GCC += \
SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
+ src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c \
+ src/portable/st/stm32_fsdev/fsdev_common.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \
diff --git a/hw/bsp/stm32g4/family.cmake b/hw/bsp/stm32g4/family.cmake
index 7e8b319b8..85201ce61 100644
--- a/hw/bsp/stm32g4/family.cmake
+++ b/hw/bsp/stm32g4/family.cmake
@@ -62,6 +62,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${TOP}/src/portable/st/typec/typec_stm32.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
diff --git a/hw/bsp/stm32g4/family.mk b/hw/bsp/stm32g4/family.mk
index 0abd73532..a153194ce 100644
--- a/hw/bsp/stm32g4/family.mk
+++ b/hw/bsp/stm32g4/family.mk
@@ -29,6 +29,7 @@ LDFLAGS_GCC += \
SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
+ src/portable/st/stm32_fsdev/fsdev_common.c \
src/portable/st/typec/typec_stm32.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
diff --git a/hw/bsp/stm32h5/boards/stm32h503nucleo/board.cmake b/hw/bsp/stm32h5/boards/stm32h503nucleo/board.cmake
index 1a44c3f1d..5978758fc 100644
--- a/hw/bsp/stm32h5/boards/stm32h503nucleo/board.cmake
+++ b/hw/bsp/stm32h5/boards/stm32h503nucleo/board.cmake
@@ -6,4 +6,7 @@ function(update_board TARGET)
STM32H503xx
HSE_VALUE=24000000
)
+ target_compile_definitions(${BOARD_TARGET} PUBLIC
+ CFG_EXAMPLE_VIDEO_READONLY
+ )
endfunction()
diff --git a/hw/bsp/stm32h5/boards/stm32h503nucleo/board.h b/hw/bsp/stm32h5/boards/stm32h503nucleo/board.h
index c8b5e31f5..9dd2b0466 100644
--- a/hw/bsp/stm32h5/boards/stm32h503nucleo/board.h
+++ b/hw/bsp/stm32h5/boards/stm32h503nucleo/board.h
@@ -37,24 +37,33 @@
extern "C" {
#endif
-// LED
-#define LED_PORT GPIOA
-#define LED_PIN GPIO_PIN_5
-#define LED_STATE_ON 1
+#define PINID_LED 0
+#define PINID_BUTTON 1
+#define PINID_UART_TX 2
+#define PINID_UART_RX 3
-// Button
-#define BUTTON_PORT GPIOA
-#define BUTTON_PIN GPIO_PIN_0
-#define BUTTON_STATE_ACTIVE 0
-
-// UART Enable for STLink VCOM
-#define UART_DEV USART3
-#define UART_CLK_EN __USART3_CLK_ENABLE
-#define UART_GPIO_PORT GPIOA
-#define UART_GPIO_AF GPIO_AF13_USART3
-
-#define UART_TX_PIN GPIO_PIN_3
-#define UART_RX_PIN GPIO_PIN_4
+static board_pindef_t board_pindef[] = {
+ { // LED
+ .port = GPIOA,
+ .pin_init = { .Pin = GPIO_PIN_5, .Mode = GPIO_MODE_OUTPUT_PP, .Pull = GPIO_PULLUP, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = 0 },
+ .active_state = 1
+ },
+ { // Button
+ .port = GPIOA,
+ .pin_init = { .Pin = GPIO_PIN_0, .Mode = GPIO_MODE_INPUT, .Pull = GPIO_PULLUP, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = 0 },
+ .active_state = 0
+ },
+ { // UART TX
+ .port = GPIOA,
+ .pin_init = { .Pin = GPIO_PIN_3, .Mode = GPIO_MODE_AF_PP, .Pull = GPIO_PULLUP, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = GPIO_AF13_USART3 },
+ .active_state = 0
+ },
+ { // UART RX
+ .port = GPIOA,
+ .pin_init = { .Pin = GPIO_PIN_4, .Mode = GPIO_MODE_AF_PP, .Pull = GPIO_PULLUP, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = GPIO_AF13_USART3 },
+ .active_state = 0
+ },
+};
//--------------------------------------------------------------------+
// RCC Clock
@@ -120,6 +129,15 @@ static inline void SystemClock_Config(void) {
__HAL_RCC_USB_CLK_ENABLE();
}
+static inline void board_init2(void) {
+ // Empty for this board
+}
+
+void board_vbus_set(uint8_t rhport, bool state) {
+ (void) rhport;
+ (void) state;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/hw/bsp/stm32h5/boards/stm32h503nucleo/board.mk b/hw/bsp/stm32h5/boards/stm32h503nucleo/board.mk
index 0292353ae..497dd894e 100644
--- a/hw/bsp/stm32h5/boards/stm32h503nucleo/board.mk
+++ b/hw/bsp/stm32h5/boards/stm32h503nucleo/board.mk
@@ -3,6 +3,7 @@ MCU_VARIANT = stm32h503xx
CFLAGS += \
-DSTM32H503xx \
-DHSE_VALUE=24000000 \
+ -DCFG_EXAMPLE_VIDEO_READONLY \
# For flash-jlink target
JLINK_DEVICE = stm32h503rb
diff --git a/hw/bsp/stm32h5/boards/stm32h563nucleo/board.h b/hw/bsp/stm32h5/boards/stm32h563nucleo/board.h
index adc3d751a..20c91f606 100644
--- a/hw/bsp/stm32h5/boards/stm32h563nucleo/board.h
+++ b/hw/bsp/stm32h5/boards/stm32h563nucleo/board.h
@@ -37,24 +37,33 @@
extern "C" {
#endif
-// LED
-#define LED_PORT GPIOG
-#define LED_PIN GPIO_PIN_4
-#define LED_STATE_ON 1
+#define PINID_LED 0
+#define PINID_BUTTON 1
+#define PINID_UART_TX 2
+#define PINID_UART_RX 3
-// Button
-#define BUTTON_PORT GPIOA
-#define BUTTON_PIN GPIO_PIN_0
-#define BUTTON_STATE_ACTIVE 0
-
-// UART Enable for STLink VCOM
-#define UART_DEV USART1
-#define UART_CLK_EN __USART1_CLK_ENABLE
-#define UART_GPIO_PORT GPIOA
-#define UART_GPIO_AF GPIO_AF7_USART1
-
-#define UART_TX_PIN GPIO_PIN_9
-#define UART_RX_PIN GPIO_PIN_10
+static board_pindef_t board_pindef[] = {
+ { // LED
+ .port = GPIOG,
+ .pin_init = { .Pin = GPIO_PIN_4, .Mode = GPIO_MODE_OUTPUT_PP, .Pull = GPIO_PULLUP, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = 0 },
+ .active_state = 1
+ },
+ { // Button
+ .port = GPIOA,
+ .pin_init = { .Pin = GPIO_PIN_0, .Mode = GPIO_MODE_INPUT, .Pull = GPIO_PULLUP, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = 0 },
+ .active_state = 0
+ },
+ { // UART TX
+ .port = GPIOA,
+ .pin_init = { .Pin = GPIO_PIN_9, .Mode = GPIO_MODE_AF_PP, .Pull = GPIO_PULLUP, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = GPIO_AF7_USART1 },
+ .active_state = 0
+ },
+ { // UART RX
+ .port = GPIOA,
+ .pin_init = { .Pin = GPIO_PIN_10, .Mode = GPIO_MODE_AF_PP, .Pull = GPIO_PULLUP, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = GPIO_AF7_USART1 },
+ .active_state = 0
+ },
+};
//--------------------------------------------------------------------+
// RCC Clock
@@ -128,6 +137,15 @@ static inline void SystemClock_Config(void) {
}
}
+static inline void board_init2(void) {
+ // Empty for this board
+}
+
+void board_vbus_set(uint8_t rhport, bool state) {
+ (void) rhport;
+ (void) state;
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/hw/bsp/stm32h5/boards/stm32h573i_dk/board.cmake b/hw/bsp/stm32h5/boards/stm32h573i_dk/board.cmake
index 92d6d98f0..76194ee91 100644
--- a/hw/bsp/stm32h5/boards/stm32h573i_dk/board.cmake
+++ b/hw/bsp/stm32h5/boards/stm32h573i_dk/board.cmake
@@ -5,4 +5,11 @@ function(update_board TARGET)
target_compile_definitions(${TARGET} PUBLIC
STM32H573xx
)
+ target_sources(${TARGET} PUBLIC
+ ${ST_TCPP0203}/tcpp0203.c
+ ${ST_TCPP0203}/tcpp0203_reg.c
+ )
+ target_include_directories(${TARGET} PUBLIC
+ ${ST_TCPP0203}
+ )
endfunction()
diff --git a/hw/bsp/stm32h5/boards/stm32h573i_dk/board.h b/hw/bsp/stm32h5/boards/stm32h573i_dk/board.h
index d75114397..5788837ab 100644
--- a/hw/bsp/stm32h5/boards/stm32h573i_dk/board.h
+++ b/hw/bsp/stm32h5/boards/stm32h573i_dk/board.h
@@ -37,24 +37,63 @@
extern "C" {
#endif
-// LED
-#define LED_PORT GPIOI
-#define LED_PIN GPIO_PIN_9
-#define LED_STATE_ON 1
+#include "tcpp0203.h"
-// Button
-#define BUTTON_PORT GPIOC
-#define BUTTON_PIN GPIO_PIN_13
-#define BUTTON_STATE_ACTIVE 1
+// VBUS Sense detection
+#define OTG_FS_VBUS_SENSE 1
+#define OTG_HS_VBUS_SENSE 0
-// UART Enable for STLink VCOM
-#define UART_DEV USART1
-#define UART_CLK_EN __USART1_CLK_ENABLE
-#define UART_GPIO_PORT GPIOA
-#define UART_GPIO_AF GPIO_AF7_USART1
+#define PINID_LED 0
+#define PINID_BUTTON 1
+#define PINID_UART_TX 2
+#define PINID_UART_RX 3
+#define PINID_TCPP0203_EN 4
+#define PINID_I2C_SCL 5
+#define PINID_I2C_SDA 6
+#define PINID_TCPP0203_INT 7
-#define UART_TX_PIN GPIO_PIN_9
-#define UART_RX_PIN GPIO_PIN_10
+static board_pindef_t board_pindef[] = {
+ { // LED
+ .port = GPIOI,
+ .pin_init = { .Pin = GPIO_PIN_9, .Mode = GPIO_MODE_OUTPUT_PP, .Pull = GPIO_PULLUP, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = 0 },
+ .active_state = 1
+ },
+ { // Button
+ .port = GPIOC,
+ .pin_init = { .Pin = GPIO_PIN_13, .Mode = GPIO_MODE_INPUT, .Pull = GPIO_PULLDOWN, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = 0 },
+ .active_state = 1
+ },
+ { // UART TX
+ .port = GPIOA,
+ .pin_init = { .Pin = GPIO_PIN_9, .Mode = GPIO_MODE_AF_PP, .Pull = GPIO_PULLUP, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = GPIO_AF7_USART1 },
+ .active_state = 0
+ },
+ { // UART RX
+ .port = GPIOA,
+ .pin_init = { .Pin = GPIO_PIN_10, .Mode = GPIO_MODE_AF_PP, .Pull = GPIO_PULLUP, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = GPIO_AF7_USART1 },
+ .active_state = 0
+ },
+ { // TCPP0203 VCC_EN
+ .port = GPIOG,
+ .pin_init = { .Pin = GPIO_PIN_0, .Mode = GPIO_MODE_OUTPUT_PP, .Pull = GPIO_NOPULL, .Speed = GPIO_SPEED_FREQ_LOW, .Alternate = 0 },
+ .active_state = 1
+ },
+ { // I2C4 SCL
+ .port = GPIOB,
+ .pin_init = { .Pin = GPIO_PIN_8, .Mode = GPIO_MODE_AF_OD, .Pull = GPIO_NOPULL, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = GPIO_AF6_I2C4 },
+ .active_state = 0
+ },
+ { // I2C4 SDA
+ .port = GPIOB,
+ .pin_init = { .Pin = GPIO_PIN_9, .Mode = GPIO_MODE_AF_OD, .Pull = GPIO_NOPULL, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = GPIO_AF6_I2C4 },
+ .active_state = 0
+ },
+ { // TCPP0203 INT
+ .port = GPIOG,
+ .pin_init = { .Pin = GPIO_PIN_1, .Mode = GPIO_MODE_IT_FALLING, .Pull = GPIO_PULLUP, .Speed = GPIO_SPEED_FREQ_HIGH, .Alternate = 0 },
+ .active_state = 0
+ },
+};
//--------------------------------------------------------------------+
// RCC Clock
@@ -113,6 +152,89 @@ static inline void SystemClock_Config(void) {
__HAL_RCC_USB_CLK_ENABLE();
}
+//--------------------------------------------------------------------+
+// USB PD
+//--------------------------------------------------------------------+
+static I2C_HandleTypeDef i2c_handle = {
+ .Instance = I2C4,
+ .Init = {
+ .Timing = 0x20C0EDFF, // 100kHz @ 250MHz
+ .OwnAddress1 = 0,
+ .AddressingMode = I2C_ADDRESSINGMODE_7BIT,
+ .DualAddressMode = I2C_DUALADDRESS_DISABLE,
+ .OwnAddress2 = 0,
+ .OwnAddress2Masks = I2C_OA2_NOMASK,
+ .GeneralCallMode = I2C_GENERALCALL_DISABLE,
+ .NoStretchMode = I2C_NOSTRETCH_DISABLE,
+ }
+};
+static TCPP0203_Object_t tcpp0203_obj = { 0 };
+
+int32_t board_tcpp0203_init(void) {
+ // Enable TCPP0203 VCC (GPIO already configured in pindef array)
+ board_pindef_t* pindef = &board_pindef[PINID_TCPP0203_EN];
+ HAL_GPIO_WritePin(pindef->port, pindef->pin_init.Pin, GPIO_PIN_SET);
+
+ // Initialize I2C4 for TCPP0203 (GPIO already configured in pindef array)
+ __HAL_RCC_I2C4_CLK_ENABLE();
+ __HAL_RCC_I2C4_FORCE_RESET();
+ __HAL_RCC_I2C4_RELEASE_RESET();
+ if (HAL_I2C_Init(&i2c_handle) != HAL_OK) {
+ return HAL_ERROR;
+ }
+
+ // Enable interrupt for TCPP0203 FLGn (GPIO already configured in pindef array)
+ NVIC_SetPriority(EXTI1_IRQn, 12);
+ NVIC_EnableIRQ(EXTI1_IRQn);
+
+ return 0;
+}
+
+int32_t board_tcpp0203_deinit(void) {
+ return 0;
+}
+
+int32_t i2c_readreg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) {
+ TU_ASSERT (HAL_OK == HAL_I2C_Mem_Read(&i2c_handle, DevAddr, Reg, I2C_MEMADD_SIZE_8BIT, pData, Length, 10000));
+ return 0;
+}
+
+int32_t i2c_writereg(uint16_t DevAddr, uint16_t Reg, uint8_t *pData, uint16_t Length) {
+ TU_ASSERT(HAL_OK == HAL_I2C_Mem_Write(&i2c_handle, DevAddr, Reg, I2C_MEMADD_SIZE_8BIT, pData, Length, 10000));
+ return 0;
+}
+
+static inline void board_init2(void) {
+ TCPP0203_IO_t io_ctx;
+
+ io_ctx.Address = TCPP0203_I2C_ADDRESS_X68;
+ io_ctx.Init = board_tcpp0203_init;
+ io_ctx.DeInit = board_tcpp0203_deinit;
+ io_ctx.ReadReg = i2c_readreg;
+ io_ctx.WriteReg = i2c_writereg;
+
+ TU_ASSERT(TCPP0203_RegisterBusIO(&tcpp0203_obj, &io_ctx) == TCPP0203_OK, );
+
+ TU_ASSERT(TCPP0203_Init(&tcpp0203_obj) == TCPP0203_OK, );
+
+ TU_ASSERT(TCPP0203_SetPowerMode(&tcpp0203_obj, TCPP0203_POWER_MODE_NORMAL) == TCPP0203_OK, );
+}
+
+void board_vbus_set(uint8_t rhport, bool state) {
+ (void) state;
+ if (rhport == 0) {
+ TU_ASSERT(TCPP0203_SetGateDriverProvider(&tcpp0203_obj, TCPP0203_GD_PROVIDER_SWITCH_CLOSED) == TCPP0203_OK, );
+ }
+}
+
+void EXTI1_IRQHandler(void) {
+ __HAL_GPIO_EXTI_CLEAR_IT(GPIO_PIN_1);
+ if (tcpp0203_obj.IsInitialized) {
+ TU_ASSERT(TCPP0203_SetPowerMode(&tcpp0203_obj, TCPP0203_POWER_MODE_NORMAL) == TCPP0203_OK, );
+ TU_ASSERT(TCPP0203_SetGateDriverProvider(&tcpp0203_obj, TCPP0203_GD_PROVIDER_SWITCH_CLOSED) == TCPP0203_OK, );
+ }
+}
+
#ifdef __cplusplus
}
#endif
diff --git a/hw/bsp/stm32h5/boards/stm32h573i_dk/board.mk b/hw/bsp/stm32h5/boards/stm32h573i_dk/board.mk
index b24acf89f..49743e7cd 100644
--- a/hw/bsp/stm32h5/boards/stm32h573i_dk/board.mk
+++ b/hw/bsp/stm32h5/boards/stm32h573i_dk/board.mk
@@ -5,3 +5,10 @@ CFLAGS += \
# For flash-jlink target
JLINK_DEVICE = stm32h573ii
+
+SRC_C += \
+ $(ST_TCPP0203)/tcpp0203.c \
+ $(ST_TCPP0203)/tcpp0203_reg.c \
+
+INC += \
+ $(TOP)/$(ST_TCPP0203) \
diff --git a/hw/bsp/stm32h5/family.c b/hw/bsp/stm32h5/family.c
index 983944b1c..fdb12e44f 100644
--- a/hw/bsp/stm32h5/family.c
+++ b/hw/bsp/stm32h5/family.c
@@ -46,20 +46,38 @@
TU_ATTR_UNUSED static void Error_Handler(void) {
}
+typedef struct {
+ GPIO_TypeDef* port;
+ GPIO_InitTypeDef pin_init;
+ uint8_t active_state;
+} board_pindef_t;
+
#include "board.h"
//--------------------------------------------------------------------+
// Forward USB interrupt events to TinyUSB IRQ Handler
//--------------------------------------------------------------------+
void USB_DRD_FS_IRQHandler(void) {
- tud_int_handler(0);
+ tusb_int_handler(0, true);
}
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM
//--------------------------------------------------------------------+
#ifdef UART_DEV
-UART_HandleTypeDef UartHandle;
+static UART_HandleTypeDef UartHandle = {
+ .Instance = UART_DEV,
+ .Init = {
+ .BaudRate = CFG_BOARD_UART_BAUDRATE,
+ .WordLength = UART_WORDLENGTH_8B,
+ .StopBits = UART_STOPBITS_1,
+ .Parity = UART_PARITY_NONE,
+ .HwFlowCtl = UART_HWCONTROL_NONE,
+ .Mode = UART_MODE_TX_RX,
+ .OverSampling = UART_OVERSAMPLING_16,
+ .AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT
+ }
+};
#endif
void board_init(void) {
@@ -95,51 +113,18 @@ void board_init(void) {
NVIC_SetPriority(USB_DRD_FS_IRQn, configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY);
#endif
- GPIO_InitTypeDef GPIO_InitStruct;
-
- // LED
- GPIO_InitStruct.Pin = LED_PIN;
- GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
- GPIO_InitStruct.Pull = GPIO_PULLUP;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
- HAL_GPIO_Init(LED_PORT, &GPIO_InitStruct);
-
- board_led_write(false);
-
- // Button
- GPIO_InitStruct.Pin = BUTTON_PIN;
- GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
- GPIO_InitStruct.Pull = BUTTON_STATE_ACTIVE ? GPIO_PULLDOWN : GPIO_PULLUP;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
- HAL_GPIO_Init(BUTTON_PORT, &GPIO_InitStruct);
+ for (uint8_t i = 0; i < TU_ARRAY_SIZE(board_pindef); i++) {
+ HAL_GPIO_Init(board_pindef[i].port, &board_pindef[i].pin_init);
+ }
#ifdef UART_DEV
UART_CLK_EN();
-
- // UART
- GPIO_InitStruct.Pin = UART_TX_PIN | UART_RX_PIN;
- GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
- GPIO_InitStruct.Pull = GPIO_PULLUP;
- GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
- GPIO_InitStruct.Alternate = UART_GPIO_AF;
- HAL_GPIO_Init(UART_GPIO_PORT, &GPIO_InitStruct);
-
- UartHandle = (UART_HandleTypeDef) {
- .Instance = UART_DEV,
- .Init.BaudRate = CFG_BOARD_UART_BAUDRATE,
- .Init.WordLength = UART_WORDLENGTH_8B,
- .Init.StopBits = UART_STOPBITS_1,
- .Init.Parity = UART_PARITY_NONE,
- .Init.HwFlowCtl = UART_HWCONTROL_NONE,
- .Init.Mode = UART_MODE_TX_RX,
- .Init.OverSampling = UART_OVERSAMPLING_16,
- .AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT
- };
HAL_UART_Init(&UartHandle);
#endif
// USB Pins TODO double check USB clock and pin setup
// Configure USB DM and DP pins. This is optional, and maintained only for user guidance.
+ GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pin = (GPIO_PIN_11 | GPIO_PIN_12);
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
@@ -153,6 +138,12 @@ void board_init(void) {
#if defined (PWR_USBSCR_USB33DEN)
HAL_PWREx_EnableVddUSB();
#endif
+
+ board_init2();
+
+#if CFG_TUH_ENABLED
+ board_vbus_set(BOARD_TUH_RHPORT, 1);
+#endif
}
//--------------------------------------------------------------------+
@@ -160,12 +151,22 @@ void board_init(void) {
//--------------------------------------------------------------------+
void board_led_write(bool state) {
- GPIO_PinState pin_state = (GPIO_PinState) (state ? LED_STATE_ON : (1 - LED_STATE_ON));
- HAL_GPIO_WritePin(LED_PORT, LED_PIN, pin_state);
+#ifdef PINID_LED
+ board_pindef_t* pindef = &board_pindef[PINID_LED];
+ GPIO_PinState pin_state = state == pindef->active_state ? GPIO_PIN_SET : GPIO_PIN_RESET;
+ HAL_GPIO_WritePin(pindef->port, pindef->pin_init.Pin, pin_state);
+#else
+ (void) state;
+#endif
}
uint32_t board_button_read(void) {
- return BUTTON_STATE_ACTIVE == HAL_GPIO_ReadPin(BUTTON_PORT, BUTTON_PIN);
+#ifdef PINID_BUTTON
+ board_pindef_t* pindef = &board_pindef[PINID_BUTTON];
+ return pindef->active_state == HAL_GPIO_ReadPin(pindef->port, pindef->pin_init.Pin);
+#else
+ return 0;
+#endif
}
size_t board_get_unique_id(uint8_t id[], size_t max_len) {
diff --git a/hw/bsp/stm32h5/family.cmake b/hw/bsp/stm32h5/family.cmake
index 6e63c4072..a8780d165 100644
--- a/hw/bsp/stm32h5/family.cmake
+++ b/hw/bsp/stm32h5/family.cmake
@@ -5,6 +5,7 @@ set(ST_PREFIX stm32${ST_FAMILY}xx)
set(ST_HAL_DRIVER ${TOP}/hw/mcu/st/stm32${ST_FAMILY}xx_hal_driver)
set(ST_CMSIS ${TOP}/hw/mcu/st/cmsis_device_${ST_FAMILY})
+set(ST_TCPP0203 ${TOP}/hw/mcu/st/stm32-tcpp0203)
set(CMSIS_5 ${TOP}/lib/CMSIS_5)
# include board specific
@@ -26,7 +27,7 @@ set(STARTUP_FILE_Clang ${STARTUP_FILE_GNU})
set(STARTUP_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/startup_${MCU_VARIANT}.s)
set(LD_FILE_GNU ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT_UPPER}_FLASH.ld)
set(LD_FILE_Clang ${LD_FILE_GNU})
-set(LD_FILE_IAR ${ST_CMSIS}/Source/Templates/iar/linker/${MCU_VARIANT}_flash.icf)
+set(LD_FILE_IAR ${CMAKE_CURRENT_LIST_DIR}/linker/${MCU_VARIANT}_flash.icf)
#------------------------------------
# BOARD_TARGET
@@ -44,6 +45,7 @@ function(family_add_board BOARD_TARGET)
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_uart_ex.c
${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_dma.c
+ ${ST_HAL_DRIVER}/Src/${ST_PREFIX}_hal_i2c.c
)
target_include_directories(${BOARD_TARGET} PUBLIC
${CMAKE_CURRENT_FUNCTION_LIST_DIR}
@@ -66,6 +68,8 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${TOP}/src/portable/st/typec/typec_stm32.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
diff --git a/hw/bsp/stm32h5/family.mk b/hw/bsp/stm32h5/family.mk
index 792edb2bb..89a2eddd5 100644
--- a/hw/bsp/stm32h5/family.mk
+++ b/hw/bsp/stm32h5/family.mk
@@ -1,6 +1,7 @@
ST_FAMILY = h5
ST_CMSIS = hw/mcu/st/cmsis_device_$(ST_FAMILY)
ST_HAL_DRIVER = hw/mcu/st/stm32$(ST_FAMILY)xx_hal_driver
+ST_TCPP0203 = hw/mcu/st/stm32-tcpp0203
include $(TOP)/$(BOARD_PATH)/board.mk
CPU_CORE ?= cortex-m33
@@ -36,6 +37,8 @@ LDFLAGS_GCC += \
SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
+ src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c \
+ src/portable/st/stm32_fsdev/fsdev_common.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \
diff --git a/hw/bsp/stm32h5/linker/STM32H503xx_FLASH.ld b/hw/bsp/stm32h5/linker/STM32H503xx_FLASH.ld
index abf618233..169ac81b7 100644
--- a/hw/bsp/stm32h5/linker/STM32H503xx_FLASH.ld
+++ b/hw/bsp/stm32h5/linker/STM32H503xx_FLASH.ld
@@ -46,7 +46,7 @@ MEMORY
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
_Min_Heap_Size = 0x200; /* required amount of heap */
-_Min_Stack_Size = 0x400; /* required amount of stack */
+_Min_Stack_Size = 0x1000; /* required amount of stack */
/* Sections */
diff --git a/hw/bsp/stm32h5/linker/STM32H523xx_FLASH.ld b/hw/bsp/stm32h5/linker/STM32H523xx_FLASH.ld
index b799892c6..633fc280e 100644
--- a/hw/bsp/stm32h5/linker/STM32H523xx_FLASH.ld
+++ b/hw/bsp/stm32h5/linker/STM32H523xx_FLASH.ld
@@ -46,7 +46,7 @@ MEMORY
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
_Min_Heap_Size = 0x200; /* required amount of heap */
-_Min_Stack_Size = 0x400; /* required amount of stack */
+_Min_Stack_Size = 0x1000; /* required amount of stack */
/* Sections */
SECTIONS
diff --git a/hw/bsp/stm32h5/linker/STM32H533xx_FLASH.ld b/hw/bsp/stm32h5/linker/STM32H533xx_FLASH.ld
index dece7a003..4d010cf9e 100644
--- a/hw/bsp/stm32h5/linker/STM32H533xx_FLASH.ld
+++ b/hw/bsp/stm32h5/linker/STM32H533xx_FLASH.ld
@@ -46,7 +46,7 @@ MEMORY
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
_Min_Heap_Size = 0x200; /* required amount of heap */
-_Min_Stack_Size = 0x400; /* required amount of stack */
+_Min_Stack_Size = 0x1000; /* required amount of stack */
/* Sections */
SECTIONS
diff --git a/hw/bsp/stm32h5/linker/STM32H562xx_FLASH.ld b/hw/bsp/stm32h5/linker/STM32H562xx_FLASH.ld
index aee2774a4..aeb799d63 100644
--- a/hw/bsp/stm32h5/linker/STM32H562xx_FLASH.ld
+++ b/hw/bsp/stm32h5/linker/STM32H562xx_FLASH.ld
@@ -46,7 +46,7 @@ MEMORY
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
_Min_Heap_Size = 0x200; /* required amount of heap */
-_Min_Stack_Size = 0x400; /* required amount of stack */
+_Min_Stack_Size = 0x1000; /* required amount of stack */
/* Sections */
SECTIONS
diff --git a/hw/bsp/stm32h5/linker/STM32H563xx_FLASH.ld b/hw/bsp/stm32h5/linker/STM32H563xx_FLASH.ld
index 129ed5170..2e8d38319 100644
--- a/hw/bsp/stm32h5/linker/STM32H563xx_FLASH.ld
+++ b/hw/bsp/stm32h5/linker/STM32H563xx_FLASH.ld
@@ -46,7 +46,7 @@ MEMORY
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
_Min_Heap_Size = 0x200; /* required amount of heap */
-_Min_Stack_Size = 0x400; /* required amount of stack */
+_Min_Stack_Size = 0x1000; /* required amount of stack */
/* Sections */
SECTIONS
diff --git a/hw/bsp/stm32h5/linker/STM32H573xx_FLASH.ld b/hw/bsp/stm32h5/linker/STM32H573xx_FLASH.ld
index eb98f3163..dd00557c0 100644
--- a/hw/bsp/stm32h5/linker/STM32H573xx_FLASH.ld
+++ b/hw/bsp/stm32h5/linker/STM32H573xx_FLASH.ld
@@ -46,7 +46,7 @@ MEMORY
_estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */
_Min_Heap_Size = 0x200; /* required amount of heap */
-_Min_Stack_Size = 0x400; /* required amount of stack */
+_Min_Stack_Size = 0x1000; /* required amount of stack */
/* Sections */
SECTIONS
diff --git a/hw/bsp/stm32h5/linker/stm32h503xx_flash.icf b/hw/bsp/stm32h5/linker/stm32h503xx_flash.icf
new file mode 100644
index 000000000..c5b783b1a
--- /dev/null
+++ b/hw/bsp/stm32h5/linker/stm32h503xx_flash.icf
@@ -0,0 +1,32 @@
+/*###ICF### Section handled by ICF editor, don't touch! ****/
+/*-Editor annotation file-*/
+/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
+/*-Specials-*/
+define symbol __ICFEDIT_intvec_start__ = 0x08000000;
+/*-Memory Regions-*/
+define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
+define symbol __ICFEDIT_region_ROM_end__ = 0x0801FFFF;
+define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
+define symbol __ICFEDIT_region_RAM_end__ = 0x20007FFF;
+
+/*-Sizes-*/
+define symbol __ICFEDIT_size_cstack__ = 0x1000;
+define symbol __ICFEDIT_size_heap__ = 0x200;
+/**** End of ICF editor section. ###ICF###*/
+
+
+define memory mem with size = 4G;
+define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
+define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
+
+define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
+define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
+
+initialize by copy { readwrite };
+do not initialize { section .noinit };
+
+place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
+
+place in ROM_region { readonly };
+place in RAM_region { readwrite,
+ block CSTACK, block HEAP };
diff --git a/hw/bsp/stm32h5/linker/stm32h523xx_flash.icf b/hw/bsp/stm32h5/linker/stm32h523xx_flash.icf
new file mode 100644
index 000000000..dc97788ae
--- /dev/null
+++ b/hw/bsp/stm32h5/linker/stm32h523xx_flash.icf
@@ -0,0 +1,32 @@
+/*###ICF### Section handled by ICF editor, don't touch! ****/
+/*-Editor annotation file-*/
+/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
+/*-Specials-*/
+define symbol __ICFEDIT_intvec_start__ = 0x08000000;
+/*-Memory Regions-*/
+define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
+define symbol __ICFEDIT_region_ROM_end__ = 0x0807FFFF;
+define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
+define symbol __ICFEDIT_region_RAM_end__ = 0x20043FFF;
+
+/*-Sizes-*/
+define symbol __ICFEDIT_size_cstack__ = 0x1000;
+define symbol __ICFEDIT_size_heap__ = 0x200;
+/**** End of ICF editor section. ###ICF###*/
+
+
+define memory mem with size = 4G;
+define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
+define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
+
+define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
+define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
+
+initialize by copy { readwrite };
+do not initialize { section .noinit };
+
+place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
+
+place in ROM_region { readonly };
+place in RAM_region { readwrite,
+ block CSTACK, block HEAP };
diff --git a/hw/bsp/stm32h5/linker/stm32h562xx_flash.icf b/hw/bsp/stm32h5/linker/stm32h562xx_flash.icf
new file mode 100644
index 000000000..b399851a3
--- /dev/null
+++ b/hw/bsp/stm32h5/linker/stm32h562xx_flash.icf
@@ -0,0 +1,32 @@
+/*###ICF### Section handled by ICF editor, don't touch! ****/
+/*-Editor annotation file-*/
+/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
+/*-Specials-*/
+define symbol __ICFEDIT_intvec_start__ = 0x08000000;
+/*-Memory Regions-*/
+define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
+define symbol __ICFEDIT_region_ROM_end__ = 0x081FFFFF;
+define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
+define symbol __ICFEDIT_region_RAM_end__ = 0x2009FFFF;
+
+/*-Sizes-*/
+define symbol __ICFEDIT_size_cstack__ = 0x1000;
+define symbol __ICFEDIT_size_heap__ = 0x200;
+/**** End of ICF editor section. ###ICF###*/
+
+
+define memory mem with size = 4G;
+define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
+define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
+
+define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
+define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
+
+initialize by copy { readwrite };
+do not initialize { section .noinit };
+
+place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
+
+place in ROM_region { readonly };
+place in RAM_region { readwrite,
+ block CSTACK, block HEAP };
diff --git a/hw/bsp/stm32h5/linker/stm32h563xx_flash.icf b/hw/bsp/stm32h5/linker/stm32h563xx_flash.icf
new file mode 100644
index 000000000..b399851a3
--- /dev/null
+++ b/hw/bsp/stm32h5/linker/stm32h563xx_flash.icf
@@ -0,0 +1,32 @@
+/*###ICF### Section handled by ICF editor, don't touch! ****/
+/*-Editor annotation file-*/
+/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
+/*-Specials-*/
+define symbol __ICFEDIT_intvec_start__ = 0x08000000;
+/*-Memory Regions-*/
+define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
+define symbol __ICFEDIT_region_ROM_end__ = 0x081FFFFF;
+define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
+define symbol __ICFEDIT_region_RAM_end__ = 0x2009FFFF;
+
+/*-Sizes-*/
+define symbol __ICFEDIT_size_cstack__ = 0x1000;
+define symbol __ICFEDIT_size_heap__ = 0x200;
+/**** End of ICF editor section. ###ICF###*/
+
+
+define memory mem with size = 4G;
+define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
+define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
+
+define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
+define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
+
+initialize by copy { readwrite };
+do not initialize { section .noinit };
+
+place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
+
+place in ROM_region { readonly };
+place in RAM_region { readwrite,
+ block CSTACK, block HEAP };
diff --git a/hw/bsp/stm32h5/linker/stm32h573xx_flash.icf b/hw/bsp/stm32h5/linker/stm32h573xx_flash.icf
new file mode 100644
index 000000000..b399851a3
--- /dev/null
+++ b/hw/bsp/stm32h5/linker/stm32h573xx_flash.icf
@@ -0,0 +1,32 @@
+/*###ICF### Section handled by ICF editor, don't touch! ****/
+/*-Editor annotation file-*/
+/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
+/*-Specials-*/
+define symbol __ICFEDIT_intvec_start__ = 0x08000000;
+/*-Memory Regions-*/
+define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
+define symbol __ICFEDIT_region_ROM_end__ = 0x081FFFFF;
+define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
+define symbol __ICFEDIT_region_RAM_end__ = 0x2009FFFF;
+
+/*-Sizes-*/
+define symbol __ICFEDIT_size_cstack__ = 0x1000;
+define symbol __ICFEDIT_size_heap__ = 0x200;
+/**** End of ICF editor section. ###ICF###*/
+
+
+define memory mem with size = 4G;
+define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
+define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
+
+define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
+define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
+
+initialize by copy { readwrite };
+do not initialize { section .noinit };
+
+place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
+
+place in ROM_region { readonly };
+place in RAM_region { readwrite,
+ block CSTACK, block HEAP };
diff --git a/hw/bsp/stm32h5/stm32h5xx_hal_conf.h b/hw/bsp/stm32h5/stm32h5xx_hal_conf.h
index d017bb06b..b4c64d56e 100644
--- a/hw/bsp/stm32h5/stm32h5xx_hal_conf.h
+++ b/hw/bsp/stm32h5/stm32h5xx_hal_conf.h
@@ -43,7 +43,6 @@ extern "C" {
/* #define HAL_EXTI_MODULE_ENABLED */
/* #define HAL_FDCAN_MODULE_ENABLED */
/* #define HAL_HCD_MODULE_ENABLED */
-/* #define HAL_I2C_MODULE_ENABLED */
/* #define HAL_I2S_MODULE_ENABLED */
/* #define HAL_IWDG_MODULE_ENABLED */
/* #define HAL_IRDA_MODULE_ENABLED */
@@ -65,6 +64,7 @@ extern "C" {
#define HAL_PWR_MODULE_ENABLED
#define HAL_CORTEX_MODULE_ENABLED
#define HAL_UART_MODULE_ENABLED
+#define HAL_I2C_MODULE_ENABLED
/* ########################## Register Callbacks selection ############################## */
/**
diff --git a/hw/bsp/stm32l0/family.cmake b/hw/bsp/stm32l0/family.cmake
index b6b0139a0..3f6622f71 100644
--- a/hw/bsp/stm32l0/family.cmake
+++ b/hw/bsp/stm32l0/family.cmake
@@ -66,6 +66,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
diff --git a/hw/bsp/stm32l0/family.mk b/hw/bsp/stm32l0/family.mk
index 921b1b413..0ae881fdf 100644
--- a/hw/bsp/stm32l0/family.mk
+++ b/hw/bsp/stm32l0/family.mk
@@ -27,6 +27,7 @@ LDFLAGS_GCC += \
SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
+ src/portable/st/stm32_fsdev/fsdev_common.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \
diff --git a/hw/bsp/stm32l4/family.cmake b/hw/bsp/stm32l4/family.cmake
index 5bc28dd5d..b1659d47a 100644
--- a/hw/bsp/stm32l4/family.cmake
+++ b/hw/bsp/stm32l4/family.cmake
@@ -67,6 +67,7 @@ function(family_configure_example TARGET RTOS)
${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/dwc2_common.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
diff --git a/hw/bsp/stm32l4/family.mk b/hw/bsp/stm32l4/family.mk
index 01d059236..fd11fd226 100644
--- a/hw/bsp/stm32l4/family.mk
+++ b/hw/bsp/stm32l4/family.mk
@@ -34,6 +34,7 @@ SRC_C += \
src/portable/synopsys/dwc2/hcd_dwc2.c \
src/portable/synopsys/dwc2/dwc2_common.c \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
+ src/portable/st/stm32_fsdev/fsdev_common.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \
diff --git a/hw/bsp/stm32u0/family.cmake b/hw/bsp/stm32u0/family.cmake
index 4f9b03109..2d3819cba 100644
--- a/hw/bsp/stm32u0/family.cmake
+++ b/hw/bsp/stm32u0/family.cmake
@@ -67,6 +67,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
diff --git a/hw/bsp/stm32u0/family.mk b/hw/bsp/stm32u0/family.mk
index d5a850050..5f25906d3 100644
--- a/hw/bsp/stm32u0/family.mk
+++ b/hw/bsp/stm32u0/family.mk
@@ -27,6 +27,7 @@ LDFLAGS_GCC += \
SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
+ src/portable/st/stm32_fsdev/fsdev_common.c \
$(ST_CMSIS)/Source/Templates/system_stm32$(ST_FAMILY)xx.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_cortex.c \
diff --git a/hw/bsp/stm32u5/family.c b/hw/bsp/stm32u5/family.c
index 0af497366..26d72d6a0 100644
--- a/hw/bsp/stm32u5/family.c
+++ b/hw/bsp/stm32u5/family.c
@@ -51,14 +51,21 @@ TU_ATTR_UNUSED static void Error_Handler(void) {
//--------------------------------------------------------------------+
// Forward USB interrupt events to TinyUSB IRQ Handler
//--------------------------------------------------------------------+
+#ifdef USB_DRD_FS
+void USB_IRQHandler(void) {
+ tusb_int_handler(0, true);
+}
+#endif
+#ifdef USB_OTG_FS
void OTG_FS_IRQHandler(void) {
- tud_int_handler(0);
+ tusb_int_handler(0, true);
}
-
+#endif
+#ifdef USB_OTG_HS
void OTG_HS_IRQHandler(void) {
- tud_int_handler(0);
+ tusb_int_handler(0, true);
}
-
+#endif
//--------------------------------------------------------------------+
// MACRO TYPEDEF CONSTANT ENUM
//--------------------------------------------------------------------+
diff --git a/hw/bsp/stm32u5/family.cmake b/hw/bsp/stm32u5/family.cmake
index 70e0c313c..58dc63ae3 100644
--- a/hw/bsp/stm32u5/family.cmake
+++ b/hw/bsp/stm32u5/family.cmake
@@ -66,6 +66,8 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${TOP}/src/portable/synopsys/dwc2/dcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/hcd_dwc2.c
${TOP}/src/portable/synopsys/dwc2/dwc2_common.c
diff --git a/hw/bsp/stm32u5/family.mk b/hw/bsp/stm32u5/family.mk
index 3694b1ca0..47aed10a9 100644
--- a/hw/bsp/stm32u5/family.mk
+++ b/hw/bsp/stm32u5/family.mk
@@ -37,12 +37,10 @@ SRC_C += \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_rcc_ex.c \
$(ST_HAL_DRIVER)/Src/stm32$(ST_FAMILY)xx_hal_uart.c
-ifeq ($(MCU_VARIANT),stm32u545xx)
+ifneq ($(filter stm32u545xx stm32u535xx,$(MCU_VARIANT)),)
SRC_C += \
- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
-else ifeq ($(MCU_VARIANT),stm32u535xx)
-SRC_C += \
- src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
+ src/portable/st/stm32_fsdev/fsdev_common.c
else
SRC_C += \
src/portable/synopsys/dwc2/dcd_dwc2.c \
diff --git a/hw/bsp/stm32wb/family.cmake b/hw/bsp/stm32wb/family.cmake
index 1a96e3d7e..6703a9b19 100644
--- a/hw/bsp/stm32wb/family.cmake
+++ b/hw/bsp/stm32wb/family.cmake
@@ -67,6 +67,7 @@ function(family_configure_example TARGET RTOS)
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/family.c
${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../board.c
${TOP}/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+ ${TOP}/src/portable/st/stm32_fsdev/fsdev_common.c
${STARTUP_FILE_${CMAKE_C_COMPILER_ID}}
)
target_include_directories(${TARGET} PUBLIC
diff --git a/hw/bsp/stm32wb/family.mk b/hw/bsp/stm32wb/family.mk
index a80ff6f5b..0b1a51cec 100644
--- a/hw/bsp/stm32wb/family.mk
+++ b/hw/bsp/stm32wb/family.mk
@@ -20,6 +20,7 @@ LDFLAGS_GCC += -specs=nosys.specs -specs=nano.specs
SRC_C += \
src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
+ src/portable/st/stm32_fsdev/fsdev_common.c \
$(ST_CMSIS)/Source/Templates/system_${ST_PREFIX}.c \
$(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal.c \
$(ST_HAL_DRIVER)/Src/${ST_PREFIX}_hal_cortex.c \
diff --git a/lib/rt-thread/SConscript b/lib/rt-thread/SConscript
index 99517a090..e7b6f2dc4 100644
--- a/lib/rt-thread/SConscript
+++ b/lib/rt-thread/SConscript
@@ -18,7 +18,8 @@ if GetDepend(["PKG_TINYUSB_DEVICE_ENABLE"]):
# BSP
if GetDepend(["SOC_FAMILY_STM32"]):
src += ["../../src/portable/synopsys/dwc2/dcd_dwc2.c",
- "../../src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c"]
+ "../../src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c",
+ "../../src/portable/st/stm32_fsdev/fsdev_common.c"]
if GetDepend(["SOC_NRF52840"]):
src += ["../../src/portable/nordic/nrf5x/dcd_nrf5x.c"]
diff --git a/src/device/usbd.c b/src/device/usbd.c
index e337a5000..1e21c667a 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -580,6 +580,8 @@ bool tud_deinit(uint8_t rhport) {
TU_LOG_USBD("USBD deinit on controller %u\r\n", rhport);
+ const uint8_t cfg_num = _usbd_dev.cfg_num;
+
// Deinit device controller driver
dcd_int_disable(rhport);
dcd_disconnect(rhport);
@@ -594,6 +596,10 @@ bool tud_deinit(uint8_t rhport) {
}
}
+ // Clear device data
+ tu_varclr(&_usbd_dev);
+ usbd_control_reset();
+
// Deinit device queue & task
osal_queue_delete(_usbd_q);
_usbd_q = NULL;
@@ -605,6 +611,11 @@ bool tud_deinit(uint8_t rhport) {
#endif
_usbd_rhport = RHPORT_INVALID;
+
+ if (cfg_num > 0) {
+ tud_umount_cb();
+ }
+
return true;
}
diff --git a/src/device/usbd.h b/src/device/usbd.h
index efde9377f..bd5a3c395 100644
--- a/src/device/usbd.h
+++ b/src/device/usbd.h
@@ -58,6 +58,7 @@ typedef union {
bool tud_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param);
// New API to replace tud_init() to init device stack on specific roothub port
+// Must be called in the same task/context as tud_task() if RTOS is used
bool tud_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init);
// Init device stack on roothub port
@@ -73,6 +74,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool tud_init (uint8_t rhport) {
}
// Deinit device stack on roothub port
+// Must be called in the same task/context as tud_task() if RTOS is used
bool tud_deinit(uint8_t rhport);
// Check if device stack is already initialized
diff --git a/src/host/usbh.h b/src/host/usbh.h
index 4b6747848..d86efbcb2 100644
--- a/src/host/usbh.h
+++ b/src/host/usbh.h
@@ -95,18 +95,23 @@ enum {
TUH_CFGID_INVALID = 0,
TUH_CFGID_RPI_PIO_USB_CONFIGURATION = 100, // cfg_param: pio_usb_configuration_t
TUH_CFGID_MAX3421 = 200,
+ TUH_CFGID_FSDEV = 300,
};
typedef struct {
- uint8_t max_nak; // max NAK per endpoint per frame to save CPU/SPI bus usage
+ uint8_t max_nak; // max NAK per endpoint per frame to save CPU/SPI bus usage (0=unlimited)
uint8_t cpuctl; // R16: CPU Control Register
uint8_t pinctl; // R17: Pin Control Register. FDUPSPI bit is ignored
} tuh_configure_max3421_t;
+typedef struct {
+ uint8_t max_nak; // max NAK per endpoint per frame to save CPU usage (0=unlimited)
+} tuh_configure_fsdev_t;
+
typedef union {
// For TUH_CFGID_RPI_PIO_USB_CONFIGURATION use pio_usb_configuration_t
-
tuh_configure_max3421_t max3421;
+ tuh_configure_fsdev_t fsdev;
} tuh_configure_param_t;
//--------------------------------------------------------------------+
@@ -145,6 +150,7 @@ void tuh_event_hook_cb(uint8_t rhport, uint32_t eventid, bool in_isr);
bool tuh_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param);
// New API to replace tuh_init() to init host stack on specific roothub port
+// Must be called in the same task/context as tuh_task() if RTOS is used
bool tuh_rhport_init(uint8_t rhport, const tusb_rhport_init_t* rh_init);
// Init host stack
@@ -160,6 +166,7 @@ TU_ATTR_ALWAYS_INLINE static inline bool tuh_init(uint8_t rhport) {
}
// Deinit host stack on rhport
+// Must be called in the same task/context as tuh_task() if RTOS is used
bool tuh_deinit(uint8_t rhport);
// Check if host stack is already initialized with any roothub ports
diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
index 64046ce17..087639d4b 100644
--- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
+++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
@@ -112,18 +112,7 @@
!(defined(TUP_USBIP_FSDEV_CH32) && CFG_TUD_WCH_USBIP_FSDEV == 0)
#include "device/dcd.h"
-
-#if defined(TUP_USBIP_FSDEV_STM32)
- #include "fsdev_stm32.h"
-#elif defined(TUP_USBIP_FSDEV_CH32)
- #include "fsdev_ch32.h"
-#elif defined(TUP_USBIP_FSDEV_AT32)
- #include "fsdev_at32.h"
-#else
- #error "Unknown USB IP"
-#endif
-
-#include "fsdev_type.h"
+#include "fsdev_common.h"
//--------------------------------------------------------------------+
// MACRO CONSTANT TYPEDEF
@@ -164,11 +153,6 @@ static bool edpt_xfer(uint8_t rhport, uint8_t ep_num, tusb_dir_t dir);
static uint16_t ep_buf_ptr; ///< Points to first free memory location
static uint32_t dcd_pma_alloc(uint16_t len, bool dbuf);
static uint8_t dcd_ep_alloc(uint8_t ep_addr, uint8_t ep_type);
-static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes);
-static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes);
-
-static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes);
-static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes);
static void edpt0_open(uint8_t rhport);
@@ -189,23 +173,9 @@ TU_ATTR_ALWAYS_INLINE static inline xfer_ctl_t *xfer_ctl_ptr(uint8_t epnum, uint
//--------------------------------------------------------------------+
bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
(void) rh_init;
- // Follow the RM mentions to use a special ordering of PDWN and FRES
- for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us
- asm("NOP");
- }
- // Perform USB peripheral reset
- FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN;
- for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us
- asm("NOP");
- }
+ fsdev_core_reset();
- FSDEV_REG->CNTR &= ~USB_CNTR_PDWN;
-
- // Wait startup time, for F042 and F070, this is <= 1 us.
- for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us
- asm("NOP");
- }
FSDEV_REG->CNTR = 0; // Enable USB
#if !defined(FSDEV_BUS_32BIT)
@@ -213,16 +183,10 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
FSDEV_REG->BTABLE = FSDEV_BTABLE_BASE;
#endif
- FSDEV_REG->ISTR = 0; // Clear pending interrupts
-
- // Reset endpoints to disabled
- for (uint32_t i = 0; i < FSDEV_EP_COUNT; i++) {
- // This doesn't clear all bits since some bits are "toggle", but does set the type to DISABLED.
- ep_write(i, 0u, false);
- }
-
+ // Enable interrupts for device mode
FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_ESOFM | USB_CNTR_CTRM |
- USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_PMAOVRM;
+ USB_CNTR_SUSPM | USB_CNTR_WKUPM | USB_CNTR_PMAOVRM;
+
handle_bus_reset(rhport);
// Enable pull-up if supported
@@ -231,6 +195,14 @@ bool dcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
return true;
}
+bool dcd_deinit(uint8_t rhport) {
+ (void)rhport;
+
+ fsdev_deinit();
+
+ return true;
+}
+
void dcd_sof_enable(uint8_t rhport, bool en) {
(void)rhport;
@@ -313,7 +285,7 @@ static void handle_ctr_setup(uint32_t ep_id) {
uint16_t rx_addr = btable_get_addr(ep_id, BTABLE_BUF_RX);
uint8_t setup_packet[8] TU_ATTR_ALIGNED(4);
- dcd_read_packet_memory(setup_packet, rx_addr, rx_count);
+ fsdev_read_packet_memory(setup_packet, rx_addr, rx_count);
// Clear CTR RX if another setup packet arrived before this, it will be discarded
ep_write_clear_ctr(ep_id, TUSB_DIR_OUT);
@@ -351,9 +323,9 @@ static void handle_ctr_rx(uint32_t ep_id) {
uint16_t pma_addr = (uint16_t) btable_get_addr(ep_id, buf_id);
if (xfer->ff) {
- dcd_read_packet_memory_ff(xfer->ff, pma_addr, rx_count);
+ fsdev_read_packet_memory_ff(xfer->ff, pma_addr, rx_count);
} else {
- dcd_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count);
+ fsdev_read_packet_memory(xfer->buffer + xfer->queued_len, pma_addr, rx_count);
}
xfer->queued_len += rx_count;
@@ -748,9 +720,9 @@ static void dcd_transmit_packet(xfer_ctl_t *xfer, uint16_t ep_ix) {
uint16_t addr_ptr = (uint16_t) btable_get_addr(ep_ix, buf_id);
if (xfer->ff) {
- dcd_write_packet_memory_ff(xfer->ff, addr_ptr, len);
+ fsdev_write_packet_memory_ff(xfer->ff, addr_ptr, len);
} else {
- dcd_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len);
+ fsdev_write_packet_memory(addr_ptr, &(xfer->buffer[xfer->queued_len]), len);
}
xfer->queued_len += len;
@@ -857,168 +829,22 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) {
ep_write(ep_idx, ep_reg, true);
}
-//--------------------------------------------------------------------+
-// PMA read/write
-//--------------------------------------------------------------------+
-
-// Write to packet memory area (PMA) from user memory
-// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT
-// - Uses unaligned for RAM (since M0 cannot access unaligned address)
-static bool dcd_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) {
- if (nbytes == 0) return true;
- uint32_t n_write = nbytes / FSDEV_BUS_SIZE;
-
- fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(dst);
- const uint8_t *src8 = src;
-
- while (n_write--) {
- pma_buf->value = fsdevbus_unaligned_read(src8);
- src8 += FSDEV_BUS_SIZE;
- pma_buf++;
- }
-
- // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit
- uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1);
- if (odd) {
- fsdev_bus_t temp = 0;
- for(uint16_t i = 0; i < odd; i++) {
- temp |= *src8++ << (i * 8);
- }
- pma_buf->value = temp;
- }
-
- return true;
+void dcd_int_enable(uint8_t rhport) {
+ fsdev_int_enable(rhport);
}
-// Read from packet memory area (PMA) to user memory.
-// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT
-// - Uses unaligned for RAM (since M0 cannot access unaligned address)
-static bool dcd_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) {
- if (nbytes == 0) return true;
- uint32_t n_read = nbytes / FSDEV_BUS_SIZE;
-
- fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(src);
- uint8_t *dst8 = (uint8_t *)dst;
-
- while (n_read--) {
- fsdevbus_unaligned_write(dst8, (fsdev_bus_t ) pma_buf->value);
- dst8 += FSDEV_BUS_SIZE;
- pma_buf++;
- }
-
- // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit
- uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1);
- if (odd) {
- fsdev_bus_t temp = pma_buf->value;
- while (odd--) {
- *dst8++ = (uint8_t) (temp & 0xfful);
- temp >>= 8;
- }
- }
-
- return true;
+void dcd_int_disable(uint8_t rhport) {
+ fsdev_int_disable(rhport);
}
-// Write to PMA from FIFO
-static bool dcd_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) {
- if (wNBytes == 0) return true;
-
- // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies
- tu_fifo_buffer_info_t info;
- tu_fifo_get_read_info(ff, &info);
-
- uint16_t cnt_lin = tu_min16(wNBytes, info.linear.len);
- uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.wrapped.len);
- uint16_t const cnt_total = cnt_lin + cnt_wrap;
-
- // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part,
- // last lin byte will be combined with wrapped part To ensure PMA is always access aligned
- uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1);
- uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1);
- uint8_t const *src8 = (uint8_t const*) info.linear.ptr;
-
- // write even linear part
- dcd_write_packet_memory(dst, src8, lin_even);
- dst += lin_even;
- src8 += lin_even;
-
- if (lin_odd == 0) {
- src8 = (uint8_t const*) info.wrapped.ptr;
- } else {
- // Combine last linear bytes + first wrapped bytes to form fsdev bus width data
- fsdev_bus_t temp = 0;
- uint16_t i;
- for(i = 0; i < lin_odd; i++) {
- temp |= *src8++ << (i * 8);
- }
-
- src8 = (uint8_t const*) info.wrapped.ptr;
- for(; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) {
- temp |= *src8++ << (i * 8);
- }
-
- dcd_write_packet_memory(dst, &temp, FSDEV_BUS_SIZE);
- dst += FSDEV_BUS_SIZE;
- }
-
- // write the rest of the wrapped part
- dcd_write_packet_memory(dst, src8, cnt_wrap);
-
- tu_fifo_advance_read_pointer(ff, cnt_total);
- return true;
+#if defined(USB_BCDR_DPPU) || defined(SYSCFG_PMC_USB_PU)
+void dcd_connect(uint8_t rhport) {
+ fsdev_connect(rhport);
}
-// Read from PMA to FIFO
-static bool dcd_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) {
- if (wNBytes == 0) return true;
-
- // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies
- // Check for first linear part
- tu_fifo_buffer_info_t info;
- tu_fifo_get_write_info(ff, &info); // We want to read from the FIFO
-
- uint16_t cnt_lin = tu_min16(wNBytes, info.linear.len);
- uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.wrapped.len);
- uint16_t cnt_total = cnt_lin + cnt_wrap;
-
- // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part,
- // last lin byte will be combined with wrapped part To ensure PMA is always access aligned
-
- uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1);
- uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1);
- uint8_t *dst8 = (uint8_t *) info.linear.ptr;
-
- // read even linear part
- dcd_read_packet_memory(dst8, src, lin_even);
- dst8 += lin_even;
- src += lin_even;
-
- if (lin_odd == 0) {
- dst8 = (uint8_t *) info.wrapped.ptr;
- } else {
- // Combine last linear bytes + first wrapped bytes to form fsdev bus width data
- fsdev_bus_t temp;
- dcd_read_packet_memory(&temp, src, FSDEV_BUS_SIZE);
- src += FSDEV_BUS_SIZE;
-
- uint16_t i;
- for (i = 0; i < lin_odd; i++) {
- *dst8++ = (uint8_t) (temp & 0xfful);
- temp >>= 8;
- }
-
- dst8 = (uint8_t *) info.wrapped.ptr;
- for (; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) {
- *dst8++ = (uint8_t) (temp & 0xfful);
- temp >>= 8;
- }
- }
-
- // read the rest of the wrapped part
- dcd_read_packet_memory(dst8, src, cnt_wrap);
-
- tu_fifo_advance_write_pointer(ff, cnt_total);
- return true;
+void dcd_disconnect(uint8_t rhport) {
+ fsdev_disconnect(rhport);
}
+#endif
#endif
diff --git a/src/portable/st/stm32_fsdev/fsdev_at32.h b/src/portable/st/stm32_fsdev/fsdev_at32.h
index deb1de2a8..6877dc131 100644
--- a/src/portable/st/stm32_fsdev/fsdev_at32.h
+++ b/src/portable/st/stm32_fsdev/fsdev_at32.h
@@ -150,8 +150,6 @@
#define USB_EPRX_DTOG2 ((uint16_t)0x2000U) /*!< EndPoint RX Data TOGgle bit1 */
#define USB_EPRX_DTOGMASK (USB_EPRX_STAT|USB_EPREG_MASK)
-#include "fsdev_type.h"
-
//--------------------------------------------------------------------+
//
//--------------------------------------------------------------------+
@@ -168,7 +166,7 @@ enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) };
#error "Unsupported MCU"
#endif
-void dcd_int_enable(uint8_t rhport) {
+TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_enable(uint8_t rhport) {
(void)rhport;
#if (CFG_TUSB_MCU == OPT_MCU_AT32F403A_407) || (CFG_TUSB_MCU == OPT_MCU_AT32F413)
// AT32F403A/407 devices allow to remap the USB interrupt vectors from
@@ -187,7 +185,7 @@ void dcd_int_enable(uint8_t rhport) {
}
}
-void dcd_int_disable(uint8_t rhport) {
+TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) {
(void)rhport;
#if (CFG_TUSB_MCU == OPT_MCU_AT32F403A_407) || (CFG_TUSB_MCU == OPT_MCU_AT32F413)
// AT32F403A/407 devices allow to remap the USB interrupt vectors from
@@ -206,20 +204,20 @@ void dcd_int_disable(uint8_t rhport) {
}
}
-void dcd_disconnect(uint8_t rhport) {
+TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) {
(void) rhport;
/* disable usb phy */
- FSDEV_REG->CNTR |= USB_CNTR_PDWN;
+ *(volatile uint32_t*)(FSDEV_REG_BASE + 0x40) |= USB_CNTR_PDWN;
/* D+ 1.5k pull-up disable, USB->cfg_bit.puo = TRUE; */
- *(uint32_t *)(FSDEV_REG_BASE+0x60) |= (1u<<1);
+ *(volatile uint32_t *)(FSDEV_REG_BASE+0x60) |= (1u<<1);
}
-void dcd_connect(uint8_t rhport) {
+TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) {
(void) rhport;
/* enable usb phy */
- FSDEV_REG->CNTR &= ~USB_CNTR_PDWN;
+ *(volatile uint32_t*)(FSDEV_REG_BASE + 0x40) &= ~USB_CNTR_PDWN;
/* Dp 1.5k pull-up enable, USB->cfg_bit.puo = 0; */
- *(uint32_t *)(FSDEV_REG_BASE+0x60) &= ~(1u<<1);
+ *(volatile uint32_t *)(FSDEV_REG_BASE+0x60) &= ~(1u<<1);
}
#endif
diff --git a/src/portable/st/stm32_fsdev/fsdev_ch32.h b/src/portable/st/stm32_fsdev/fsdev_ch32.h
index ceebb6dab..ee0057cb4 100644
--- a/src/portable/st/stm32_fsdev/fsdev_ch32.h
+++ b/src/portable/st/stm32_fsdev/fsdev_ch32.h
@@ -168,7 +168,6 @@
#define USB_EPRX_DTOG2 ((uint16_t)0x2000U) /*!< EndPoint RX Data TOGgle bit1 */
#define USB_EPRX_DTOGMASK (USB_EPRX_STAT|USB_EPREG_MASK)
-
//--------------------------------------------------------------------+
//
//--------------------------------------------------------------------+
@@ -184,26 +183,26 @@ enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) };
#error "Unsupported MCU"
#endif
-void dcd_int_enable(uint8_t rhport) {
+TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_enable(uint8_t rhport) {
(void)rhport;
for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) {
NVIC_EnableIRQ(fsdev_irq[i]);
}
}
-void dcd_int_disable(uint8_t rhport) {
+TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) {
(void)rhport;
for(uint8_t i=0; i < FSDEV_IRQ_NUM; i++) {
NVIC_DisableIRQ(fsdev_irq[i]);
}
}
-void dcd_disconnect(uint8_t rhport) {
+TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) {
(void) rhport;
EXTEN->EXTEN_CTR &= ~EXTEN_USBD_PU_EN;
}
-void dcd_connect(uint8_t rhport) {
+TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) {
(void) rhport;
EXTEN->EXTEN_CTR |= EXTEN_USBD_PU_EN;
}
diff --git a/src/portable/st/stm32_fsdev/fsdev_common.c b/src/portable/st/stm32_fsdev/fsdev_common.c
new file mode 100644
index 000000000..5d60ad9a2
--- /dev/null
+++ b/src/portable/st/stm32_fsdev/fsdev_common.c
@@ -0,0 +1,289 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2024 Ha Thach (tinyusb.org)
+ * Copyright (c) 2025, HiFiPhile (Zixun LI)
+ *
+ * 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 defined(TUP_USBIP_FSDEV) && (CFG_TUH_ENABLED || CFG_TUD_ENABLED)
+
+#include "fsdev_common.h"
+
+//--------------------------------------------------------------------+
+// Global
+//--------------------------------------------------------------------+
+
+// Reset the USB Core
+void fsdev_core_reset(void) {
+ // Perform USB peripheral reset
+ FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN;
+ for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us
+ asm("NOP");
+ }
+
+ FSDEV_REG->CNTR &= ~USB_CNTR_PDWN;
+
+ // Wait startup time, for F042 and F070, this is <= 1 us.
+ for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us
+ asm("NOP");
+ }
+
+ // Clear pending interrupts
+ FSDEV_REG->ISTR = 0;
+}
+
+// De-initialize the USB Core
+void fsdev_deinit(void) {
+ // Disable all interrupts and force USB reset
+ FSDEV_REG->CNTR = USB_CNTR_FRES;
+
+ // Clear pending interrupts
+ FSDEV_REG->ISTR = 0;
+
+ // Put USB peripheral in power down mode
+ FSDEV_REG->CNTR = USB_CNTR_FRES | USB_CNTR_PDWN;
+ for (volatile uint32_t i = 0; i < 200; i++) { // should be a few us
+ asm("NOP");
+ }
+}
+
+
+//--------------------------------------------------------------------+
+// PMA read/write
+//--------------------------------------------------------------------+
+
+// Write to packet memory area (PMA) from user memory
+// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT
+// - Uses unaligned for RAM (since M0 cannot access unaligned address)
+bool fsdev_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes) {
+ if (nbytes == 0) {
+ return true;
+ }
+ uint32_t n_write = nbytes / FSDEV_BUS_SIZE;
+
+ fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(dst);
+ const uint8_t *src8 = src;
+
+ while (n_write--) {
+ pma_buf->value = fsdevbus_unaligned_read(src8);
+ src8 += FSDEV_BUS_SIZE;
+ pma_buf++;
+ }
+
+ // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit
+ uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1);
+ if (odd) {
+ fsdev_bus_t temp = 0;
+ for(uint16_t i = 0; i < odd; i++) {
+ temp |= *src8++ << (i * 8);
+ }
+ pma_buf->value = temp;
+ }
+
+ return true;
+}
+
+// Read from packet memory area (PMA) to user memory.
+// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT
+// - Uses unaligned for RAM (since M0 cannot access unaligned address)
+bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes) {
+ if (nbytes == 0) {
+ return true;
+ }
+ uint32_t n_read = nbytes / FSDEV_BUS_SIZE;
+
+ fsdev_pma_buf_t* pma_buf = PMA_BUF_AT(src);
+ uint8_t *dst8 = (uint8_t *)dst;
+
+ while (n_read--) {
+ fsdevbus_unaligned_write(dst8, (fsdev_bus_t ) pma_buf->value);
+ dst8 += FSDEV_BUS_SIZE;
+ pma_buf++;
+ }
+
+ // odd bytes e.g 1 for 16-bit or 1-3 for 32-bit
+ uint16_t odd = nbytes & (FSDEV_BUS_SIZE - 1);
+ if (odd) {
+ fsdev_bus_t temp = pma_buf->value;
+ while (odd--) {
+ *dst8++ = (uint8_t) (temp & 0xfful);
+ temp >>= 8;
+ }
+ }
+
+ return true;
+}
+
+// Write to PMA from FIFO
+bool fsdev_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes) {
+ if (wNBytes == 0) {
+ return true;
+ }
+
+ // Since we copy from a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies
+ tu_fifo_buffer_info_t info;
+ tu_fifo_get_read_info(ff, &info);
+
+ uint16_t cnt_lin = tu_min16(wNBytes, info.linear.len);
+ uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.wrapped.len);
+ uint16_t const cnt_total = cnt_lin + cnt_wrap;
+
+ // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part,
+ // last lin byte will be combined with wrapped part To ensure PMA is always access aligned
+ uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1);
+ uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1);
+ uint8_t const *src8 = (uint8_t const*) info.linear.ptr;
+
+ // write even linear part
+ fsdev_write_packet_memory(dst, src8, lin_even);
+ dst += lin_even;
+ src8 += lin_even;
+
+ if (lin_odd == 0) {
+ src8 = (uint8_t const*) info.wrapped.ptr;
+ } else {
+ // Combine last linear bytes + first wrapped bytes to form fsdev bus width data
+ fsdev_bus_t temp = 0;
+ uint16_t i;
+ for(i = 0; i < lin_odd; i++) {
+ temp |= *src8++ << (i * 8);
+ }
+
+ src8 = (uint8_t const*) info.wrapped.ptr;
+ for(; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) {
+ temp |= *src8++ << (i * 8);
+ }
+
+ fsdev_write_packet_memory(dst, &temp, FSDEV_BUS_SIZE);
+ dst += FSDEV_BUS_SIZE;
+ }
+
+ // write the rest of the wrapped part
+ fsdev_write_packet_memory(dst, src8, cnt_wrap);
+
+ tu_fifo_advance_read_pointer(ff, cnt_total);
+ return true;
+}
+
+// Read from PMA to FIFO
+bool fsdev_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes) {
+ if (wNBytes == 0) {
+ return true;
+ }
+
+ // Since we copy into a ring buffer FIFO, a wrap might occur making it necessary to conduct two copies
+ // Check for first linear part
+ tu_fifo_buffer_info_t info;
+ tu_fifo_get_write_info(ff, &info); // We want to read from the FIFO
+
+ uint16_t cnt_lin = tu_min16(wNBytes, info.linear.len);
+ uint16_t cnt_wrap = tu_min16(wNBytes - cnt_lin, info.wrapped.len);
+ uint16_t cnt_total = cnt_lin + cnt_wrap;
+
+ // We want to read from the FIFO and write it into the PMA, if LIN part is ODD and has WRAPPED part,
+ // last lin byte will be combined with wrapped part To ensure PMA is always access aligned
+
+ uint16_t lin_even = cnt_lin & ~(FSDEV_BUS_SIZE - 1);
+ uint16_t lin_odd = cnt_lin & (FSDEV_BUS_SIZE - 1);
+ uint8_t *dst8 = (uint8_t *) info.linear.ptr;
+
+ // read even linear part
+ fsdev_read_packet_memory(dst8, src, lin_even);
+ dst8 += lin_even;
+ src += lin_even;
+
+ if (lin_odd == 0) {
+ dst8 = (uint8_t *) info.wrapped.ptr;
+ } else {
+ // Combine last linear bytes + first wrapped bytes to form fsdev bus width data
+ fsdev_bus_t temp;
+ fsdev_read_packet_memory(&temp, src, FSDEV_BUS_SIZE);
+ src += FSDEV_BUS_SIZE;
+
+ uint16_t i;
+ for (i = 0; i < lin_odd; i++) {
+ *dst8++ = (uint8_t) (temp & 0xfful);
+ temp >>= 8;
+ }
+
+ dst8 = (uint8_t *) info.wrapped.ptr;
+ for (; i < FSDEV_BUS_SIZE && cnt_wrap > 0; i++, cnt_wrap--) {
+ *dst8++ = (uint8_t) (temp & 0xfful);
+ temp >>= 8;
+ }
+ }
+
+ // read the rest of the wrapped part
+ fsdev_read_packet_memory(dst8, src, cnt_wrap);
+
+ tu_fifo_advance_write_pointer(ff, cnt_total);
+ return true;
+}
+
+//--------------------------------------------------------------------+
+// BTable Helper
+//--------------------------------------------------------------------+
+
+// Aligned buffer size according to hardware
+uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block) {
+ /* The STM32 full speed USB peripheral supports only a limited set of
+ * buffer sizes given by the RX buffer entry format in the USB_BTABLE. */
+ uint16_t block_in_bytes;
+ if (size > 62) {
+ block_in_bytes = 32;
+ *blsize = 1;
+ *num_block = tu_div_ceil(size, 32);
+ } else {
+ block_in_bytes = 2;
+ *blsize = 0;
+ *num_block = tu_div_ceil(size, 2);
+ }
+
+ return (*num_block) * block_in_bytes;
+}
+
+// Set RX buffer size
+void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount) {
+ uint8_t blsize, num_block;
+ (void) pma_align_buffer_size(wCount, &blsize, &num_block);
+
+ /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */
+ uint16_t bl_nb = (blsize << 15) | ((num_block - blsize) << 10);
+ if (bl_nb == 0) {
+ // zlp but 0 is invalid value, set blsize to 1 (32 bytes)
+ // Note: lower value can cause PMAOVR on setup with ch32v203
+ bl_nb = 1 << 15;
+ }
+
+#ifdef FSDEV_BUS_32BIT
+ uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr;
+ count_addr = (bl_nb << 16) | (count_addr & 0x0000FFFFu);
+ FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr;
+#else
+ FSDEV_BTABLE->ep16[ep_id][buf_id].count = bl_nb;
+#endif
+}
+
+#endif
diff --git a/src/portable/st/stm32_fsdev/fsdev_type.h b/src/portable/st/stm32_fsdev/fsdev_common.h
similarity index 73%
rename from src/portable/st/stm32_fsdev/fsdev_type.h
rename to src/portable/st/stm32_fsdev/fsdev_common.h
index cf36576bb..0c67ee0c7 100644
--- a/src/portable/st/stm32_fsdev/fsdev_type.h
+++ b/src/portable/st/stm32_fsdev/fsdev_common.h
@@ -1,8 +1,9 @@
/*
* The MIT License (MIT)
*
- * Copyright(c) N Conrad
- * Copyright(c) 2024, hathach (tinyusb.org)
+ * Copyright (c) N Conrad
+ * Copyright (c) 2024, hathach (tinyusb.org)
+ * Copyright (c) 2025, HiFiPhile (Zixun LI)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -25,14 +26,32 @@
* This file is part of the TinyUSB stack.
*/
-#ifndef TUSB_FSDEV_TYPE_H
-#define TUSB_FSDEV_TYPE_H
+#ifndef TUSB_FSDEV_COMMON_H
+#define TUSB_FSDEV_COMMON_H
-#ifdef __cplusplus
- extern "C" {
+#include "common/tusb_common.h"
+
+#if CFG_TUD_ENABLED
+#include "device/dcd.h"
#endif
-#include "stdint.h"
+#if CFG_TUH_ENABLED
+#include "host/hcd.h"
+#endif
+
+#if defined(TUP_USBIP_FSDEV_STM32)
+ #include "fsdev_stm32.h"
+#elif defined(TUP_USBIP_FSDEV_CH32)
+ #include "fsdev_ch32.h"
+#elif defined(TUP_USBIP_FSDEV_AT32)
+ #include "fsdev_at32.h"
+#else
+ #error "Unknown USB IP"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
// If sharing with CAN, one can set this to be non-zero to give CAN space where it wants it
// Both of these MUST be a multiple of 2, and are in byte units.
@@ -174,6 +193,9 @@ typedef enum {
#define EP_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8)))
#define EP_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 0 : 8)))
+#define CH_STAT_MASK(_dir) (3u << (USB_EPTX_STAT_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0)))
+#define CH_DTOG_MASK(_dir) (1u << (USB_EP_DTOG_TX_Pos + ((_dir) == TUSB_DIR_IN ? 8 : 0)))
+
//--------------------------------------------------------------------+
// Endpoint Helper
// - CTR is write 0 to clear
@@ -186,13 +208,13 @@ TU_ATTR_ALWAYS_INLINE static inline uint32_t ep_read(uint32_t ep_id) {
TU_ATTR_ALWAYS_INLINE static inline void ep_write(uint32_t ep_id, uint32_t value, bool need_exclusive) {
if (need_exclusive) {
- dcd_int_disable(0);
+ fsdev_int_disable(0);
}
FSDEV_REG->ep[ep_id].reg = (fsdev_bus_t) value;
if (need_exclusive) {
- dcd_int_enable(0);
+ fsdev_int_enable(0);
}
}
@@ -216,6 +238,35 @@ TU_ATTR_ALWAYS_INLINE static inline bool ep_is_iso(uint32_t reg) {
return (reg & USB_EP_TYPE_MASK) == USB_EP_ISOCHRONOUS;
}
+//--------------------------------------------------------------------+
+// Channel Helper
+// - Direction is opposite to endpoint direction
+//--------------------------------------------------------------------+
+
+TU_ATTR_ALWAYS_INLINE static inline uint32_t ch_read(uint32_t ch_id) {
+ return ep_read(ch_id);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void ch_write(uint32_t ch_id, uint32_t value, bool need_exclusive) {
+ ep_write(ch_id, value, need_exclusive);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void ch_write_clear_ctr(uint32_t ch_id, tusb_dir_t dir) {
+ uint32_t reg = FSDEV_REG->ep[ch_id].reg;
+ reg |= USB_EP_CTR_TX | USB_EP_CTR_RX;
+ reg &= USB_EPREG_MASK;
+ reg &= ~(1 << (USB_EP_CTR_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0)));
+ ep_write(ch_id, reg, false);
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void ch_change_status(uint32_t* reg, tusb_dir_t dir, ep_stat_t state) {
+ *reg ^= (state << (USB_EPTX_STAT_Pos + (dir == TUSB_DIR_IN ? 8 : 0)));
+}
+
+TU_ATTR_ALWAYS_INLINE static inline void ch_change_dtog(uint32_t* reg, tusb_dir_t dir, uint8_t state) {
+ *reg ^= (state << (USB_EP_DTOG_TX_Pos + (dir == TUSB_DIR_IN ? 8 : 0)));
+}
+
//--------------------------------------------------------------------+
// BTable Helper
//--------------------------------------------------------------------+
@@ -260,48 +311,40 @@ TU_ATTR_ALWAYS_INLINE static inline void btable_set_count(uint32_t ep_id, uint8_
#endif
}
-/* Aligned buffer size according to hardware */
-TU_ATTR_ALWAYS_INLINE static inline uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block) {
- /* The STM32 full speed USB peripheral supports only a limited set of
- * buffer sizes given by the RX buffer entry format in the USB_BTABLE. */
- uint16_t block_in_bytes;
- if (size > 62) {
- block_in_bytes = 32;
- *blsize = 1;
- *num_block = tu_div_ceil(size, 32);
- } else {
- block_in_bytes = 2;
- *blsize = 0;
- *num_block = tu_div_ceil(size, 2);
- }
+// Reset the USB Core
+void fsdev_core_reset(void);
- return (*num_block) * block_in_bytes;
-}
+// De-initialize the USB Core
+void fsdev_deinit(void);
-TU_ATTR_ALWAYS_INLINE static inline void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount) {
- uint8_t blsize, num_block;
- (void) pma_align_buffer_size(wCount, &blsize, &num_block);
+// Aligned buffer size according to hardware
+uint16_t pma_align_buffer_size(uint16_t size, uint8_t* blsize, uint8_t* num_block);
- /* Encode into register. When BLSIZE==1, we need to subtract 1 block count */
- uint16_t bl_nb = (blsize << 15) | ((num_block - blsize) << 10);
- if (bl_nb == 0) {
- // zlp but 0 is invalid value, set blsize to 1 (32 bytes)
- // Note: lower value can cause PMAOVR on setup with ch32v203
- bl_nb = 1 << 15;
- }
+// Set RX buffer size
+void btable_set_rx_bufsize(uint32_t ep_id, uint8_t buf_id, uint16_t wCount);
-#ifdef FSDEV_BUS_32BIT
- uint32_t count_addr = FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr;
- count_addr = (bl_nb << 16) | (count_addr & 0x0000FFFFu);
- FSDEV_BTABLE->ep32[ep_id][buf_id].count_addr = count_addr;
-#else
- FSDEV_BTABLE->ep16[ep_id][buf_id].count = bl_nb;
-#endif
+//--------------------------------------------------------------------+
+// PMA (Packet Memory Area) Access
+//--------------------------------------------------------------------+
-}
+// Write to packet memory area (PMA) from user memory
+// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT
+// - Uses unaligned for RAM (since M0 cannot access unaligned address)
+bool fsdev_write_packet_memory(uint16_t dst, const void *__restrict src, uint16_t nbytes);
+
+// Read from packet memory area (PMA) to user memory.
+// - Packet memory must be either strictly 16-bit or 32-bit depending on FSDEV_BUS_32BIT
+// - Uses unaligned for RAM (since M0 cannot access unaligned address)
+bool fsdev_read_packet_memory(void *__restrict dst, uint16_t src, uint16_t nbytes);
+
+// Write to PMA from FIFO
+bool fsdev_write_packet_memory_ff(tu_fifo_t *ff, uint16_t dst, uint16_t wNBytes);
+
+// Read from PMA to FIFO
+bool fsdev_read_packet_memory_ff(tu_fifo_t *ff, uint16_t src, uint16_t wNBytes);
#ifdef __cplusplus
- }
+}
#endif
-#endif
+#endif /* TUSB_FSDEV_COMMON_H */
diff --git a/src/portable/st/stm32_fsdev/fsdev_stm32.h b/src/portable/st/stm32_fsdev/fsdev_stm32.h
index e7a57aca0..4b7d3d301 100644
--- a/src/portable/st/stm32_fsdev/fsdev_stm32.h
+++ b/src/portable/st/stm32_fsdev/fsdev_stm32.h
@@ -371,7 +371,7 @@ static const IRQn_Type fsdev_irq[] = {
};
enum { FSDEV_IRQ_NUM = TU_ARRAY_SIZE(fsdev_irq) };
-void dcd_int_enable(uint8_t rhport) {
+TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_enable(uint8_t rhport) {
(void)rhport;
// forces write to RAM before allowing ISR to execute
@@ -394,7 +394,7 @@ void dcd_int_enable(uint8_t rhport) {
}
}
-void dcd_int_disable(uint8_t rhport) {
+TU_ATTR_ALWAYS_INLINE static inline void fsdev_int_disable(uint8_t rhport) {
(void)rhport;
#if CFG_TUSB_MCU == OPT_MCU_STM32F3 && defined(SYSCFG_CFGR1_USB_IT_RMP)
@@ -419,28 +419,27 @@ void dcd_int_disable(uint8_t rhport) {
// Define only on MCU with internal pull-up. BSP can define on MCU without internal PU.
#if defined(USB_BCDR_DPPU)
-void dcd_disconnect(uint8_t rhport) {
+TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) {
(void)rhport;
USB->BCDR &= ~(USB_BCDR_DPPU);
}
-void dcd_connect(uint8_t rhport) {
+TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) {
(void)rhport;
USB->BCDR |= USB_BCDR_DPPU;
}
#elif defined(SYSCFG_PMC_USB_PU) // works e.g. on STM32L151
-void dcd_disconnect(uint8_t rhport) {
+TU_ATTR_ALWAYS_INLINE static inline void fsdev_disconnect(uint8_t rhport) {
(void)rhport;
SYSCFG->PMC &= ~(SYSCFG_PMC_USB_PU);
}
-void dcd_connect(uint8_t rhport) {
+TU_ATTR_ALWAYS_INLINE static inline void fsdev_connect(uint8_t rhport) {
(void)rhport;
SYSCFG->PMC |= SYSCFG_PMC_USB_PU;
}
#endif
-
#endif /* TUSB_FSDEV_STM32_H */
diff --git a/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c
new file mode 100644
index 000000000..da9c6961c
--- /dev/null
+++ b/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c
@@ -0,0 +1,878 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2025 HiFiPhile (Zixun LI)
+ *
+ * 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.
+ */
+
+/**********************************************
+ * This driver provides USB Host controller support for STM32 MCUs with "USB A"/"PCD"/"HCD" peripheral.
+ * This covers these MCU families:
+ *
+ * C0 2048 byte buffer; 32-bit bus; host mode
+ * G0 2048 byte buffer; 32-bit bus; host mode
+ * U3 2048 byte buffer; 32-bit bus; host mode
+ * H5 2048 byte buffer; 32-bit bus; host mode
+ * U535, U545 2048 byte buffer; 32-bit bus; host mode
+ *
+ */
+
+#include "tusb_option.h"
+
+#if CFG_TUH_ENABLED && defined(TUP_USBIP_FSDEV) && \
+ TU_CHECK_MCU(OPT_MCU_STM32C0, OPT_MCU_STM32G0, OPT_MCU_STM32H5, OPT_MCU_STM32U5)
+
+#include "host/hcd.h"
+#include "host/usbh.h"
+#include "fsdev_common.h"
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF
+//--------------------------------------------------------------------+
+
+// Debug level for FSDEV
+#define FSDEV_DEBUG 3
+
+// Max number of endpoints application can open, can be larger than FSDEV_EP_COUNT
+#ifndef CFG_TUH_FSDEV_ENDPOINT_MAX
+ #define CFG_TUH_FSDEV_ENDPOINT_MAX 16u
+#endif
+
+TU_VERIFY_STATIC(CFG_TUH_FSDEV_ENDPOINT_MAX <= 255, "currently only use 8-bit for index");
+
+#if CFG_TUSB_MCU == OPT_MCU_STM32H5
+ #define CPU_FREQUENCY_MHZ 250U
+#elif CFG_TUSB_MCU == OPT_MCU_STM32U5
+ #define CPU_FREQUENCY_MHZ 160U
+#elif CFG_TUSB_MCU == OPT_MCU_STM32U3
+ #define CPU_FREQUENCY_MHZ 96U
+#elif CFG_TUSB_MCU == OPT_MCU_STM32G0
+ #define CPU_FREQUENCY_MHZ 64U
+#elif CFG_TUSB_MCU == OPT_MCU_STM32C0
+ #define CPU_FREQUENCY_MHZ 48U
+#else
+ #error "CPU_FREQUENCY_MHZ not defined for this STM32 MCU"
+#endif
+
+enum {
+ HCD_XFER_ERROR_MAX = 3,
+ HCD_XFER_NAK_MAX = 15,
+ HCD_XFER_NAK_DEFAULT = 3,
+};
+
+// Host driver struct for each opened endpoint
+typedef struct {
+ uint8_t *buffer;
+ uint16_t buflen;
+ uint16_t queued_len;
+ uint16_t max_packet_size;
+ uint8_t dev_addr;
+ uint8_t ep_addr;
+ uint8_t ep_type;
+ uint8_t interval;
+ struct TU_ATTR_PACKED {
+ uint8_t ls_pre : 1;
+ uint8_t allocated : 1;
+ uint8_t next_setup : 1;
+ uint8_t pid : 1;
+ };
+} hcd_endpoint_t;
+
+// Channel direction state
+typedef struct {
+ hcd_endpoint_t* edpt;
+ struct TU_ATTR_PACKED {
+ uint8_t allocated : 1;
+ uint8_t retry : 3;
+ uint8_t nak : 4; // Max NAK count in current frame
+ };
+} hcd_channel_dir_t;
+
+// Additional info for each channel when it is active
+typedef struct {
+ uint8_t dev_addr;
+ uint8_t ep_num;
+ uint8_t ep_type;
+ hcd_channel_dir_t out, in;
+} hcd_channel_t;
+
+static struct {
+ hcd_channel_t channel[FSDEV_EP_COUNT];
+ hcd_endpoint_t edpt[CFG_TUH_FSDEV_ENDPOINT_MAX];
+ bool connected;
+} _hcd_data;
+
+static tuh_configure_fsdev_t _tuh_cfg = {
+ .max_nak = HCD_XFER_NAK_DEFAULT,
+};
+
+//--------------------------------------------------------------------+
+// Prototypes
+//--------------------------------------------------------------------+
+
+static uint8_t endpoint_alloc(void);
+static uint8_t endpoint_find(uint8_t dev_addr, uint8_t ep_addr);
+static uint32_t hcd_pma_alloc(uint8_t channel, tusb_dir_t dir, uint16_t len);
+static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type);
+static bool edpt_xfer_kickoff(uint8_t ep_id);
+static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir);
+static void edpoint_close(uint8_t ep_id);
+static void port_status_handler(uint8_t rhport, bool in_isr);
+static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir);
+static void ch_handle_nak(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir);
+static void ch_handle_stall(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir);
+static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir);
+
+//--------------------------------------------------------------------+
+// Inline Functions
+//--------------------------------------------------------------------+
+
+static inline void endpoint_dealloc(hcd_endpoint_t* edpt) {
+ edpt->allocated = 0;
+}
+
+static inline void channel_dealloc(hcd_channel_t* ch, tusb_dir_t dir) {
+ if (dir == TUSB_DIR_OUT) {
+ ch->out.allocated = 0;
+ } else {
+ ch->in.allocated = 0;
+ }
+}
+
+// Write channel state in specified direction
+static inline void channel_write_status(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir, ep_stat_t state, bool need_exclusive) {
+ ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir);
+ ch_change_status(&ch_reg, dir, state);
+ ch_write(ch_id, ch_reg, need_exclusive);
+}
+
+static inline uint16_t channel_get_rx_count(uint8_t ch_id) {
+ /* https://www.st.com/resource/en/errata_sheet/es0561-stm32h503cbebkbrb-device-errata-stmicroelectronics.pdf
+ * https://www.st.com/resource/en/errata_sheet/es0587-stm32u535xx-and-stm32u545xx-device-errata-stmicroelectronics.pdf
+ * From H503/U535 errata: Buffer description table update completes after CTR interrupt triggers
+ * Description:
+ * - During OUT transfers, the correct transfer interrupt (CTR) is triggered a little before the last USB SRAM accesses
+ * have completed. If the software responds quickly to the interrupt, the full buffer contents may not be correct.
+ * Workaround:
+ * - Software should ensure that a small delay is included before accessing the SRAM contents. This delay
+ * should be 800 ns in Full Speed mode and 6.4 μs in Low Speed mode
+ *
+ * Note: this errata may also apply to G0, U5, H5 etc.
+ *
+ * We choose the delay count based on max CPU frequency (in MHz) to ensure the delay is at least the required time.
+ */
+
+ uint32_t ch_reg = ch_read(ch_id);
+ if (FSDEV_REG->ISTR & USB_ISTR_LS_DCONN || ch_reg & USB_CHEP_LSEP) {
+ // Low speed mode: 6.4 us delay -> about 2 cycles per MHz
+ volatile uint32_t cycle_count = CPU_FREQUENCY_MHZ * 2U;
+ while (cycle_count > 0U) {
+ cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare)
+ }
+ } else {
+ // Full speed mode: 800 ns delay -> about 0.25 cycles per MHz
+ volatile uint32_t cycle_count = CPU_FREQUENCY_MHZ / 4U;
+ while (cycle_count > 0U) {
+ cycle_count--; // each count take 3 cycles (1 for sub, jump, and compare)
+ }
+ }
+
+ return btable_get_count(ch_id, BTABLE_BUF_RX);
+}
+
+//--------------------------------------------------------------------+
+// Controller API
+//--------------------------------------------------------------------+
+
+// Optional HCD configuration, called by tuh_configure()
+bool hcd_configure(uint8_t rhport, uint32_t cfg_id, const void* cfg_param) {
+ (void) rhport;
+ TU_VERIFY(cfg_id == TUH_CFGID_FSDEV && cfg_param != NULL);
+
+ tuh_configure_param_t const* cfg = (tuh_configure_param_t const*) cfg_param;
+ _tuh_cfg.max_nak = tu_min8(cfg->fsdev.max_nak, HCD_XFER_NAK_MAX);
+ return true;
+}
+
+// Initialize controller to host mode
+bool hcd_init(uint8_t rhport, const tusb_rhport_init_t* rh_init) {
+ (void) rh_init;
+
+ fsdev_core_reset();
+
+ FSDEV_REG->CNTR = USB_CNTR_HOST; // Enable USB in Host mode
+
+ tu_memclr(&_hcd_data, sizeof(_hcd_data));
+
+ // Enable interrupts for host mode
+ FSDEV_REG->CNTR |= USB_CNTR_RESETM | USB_CNTR_CTRM | USB_CNTR_SOFM | USB_CNTR_SUSPM |
+ USB_CNTR_WKUPM | USB_CNTR_ERRM | USB_CNTR_PMAOVRM;
+
+ // Initialize port state
+ _hcd_data.connected = false;
+
+ fsdev_connect(rhport);
+
+ // If DCON_STAT is already set, the controller sometimes misses the initial connection interrupt
+ if (FSDEV_REG->ISTR & USB_ISTR_DCON_STAT) {
+ // Wait DP/DM stabilize time
+ volatile uint32_t cycle_count = CPU_FREQUENCY_MHZ / 4U;
+ while (cycle_count > 0U) {
+ cycle_count--;
+ }
+ port_status_handler(rhport, false);
+ }
+
+ return true;
+}
+
+bool hcd_deinit(uint8_t rhport) {
+ (void)rhport;
+
+ fsdev_disconnect(rhport);
+
+ fsdev_deinit();
+
+ return true;
+}
+
+//--------------------------------------------------------------------+
+// Interrupt Helper Functions
+//--------------------------------------------------------------------+
+
+static inline void sof_handler(void) {
+ // Reset NAK counters for all active channels
+ for (uint8_t ch_id = 0; ch_id < FSDEV_EP_COUNT; ch_id++) {
+ hcd_channel_t* channel = &_hcd_data.channel[ch_id];
+ if (channel->out.allocated) {
+ channel->out.nak = 0;
+ }
+ if (channel->in.allocated) {
+ channel->in.nak = 0;
+ }
+ }
+}
+
+static void port_status_handler(uint8_t rhport, bool in_isr) {
+ uint32_t const fnr_reg = FSDEV_REG->FNR;
+ uint32_t const istr_reg = FSDEV_REG->ISTR;
+ // SE0 detected USB Disconnected state
+ if ((fnr_reg & (USB_FNR_RXDP | USB_FNR_RXDM)) == 0U) {
+ _hcd_data.connected = false;
+ hcd_event_device_remove(rhport, in_isr);
+ return;
+ }
+
+ if (!_hcd_data.connected) {
+ // J-state or K-state detected & LastState=Disconnected
+ if (((fnr_reg & USB_FNR_RXDP) != 0U) || ((istr_reg & USB_ISTR_LS_DCONN) != 0U)) {
+ _hcd_data.connected = true;
+ hcd_event_device_attach(rhport, in_isr);
+ }
+ } else {
+ // J-state or K-state detected & lastState=Connected: a Missed disconnection is detected
+ if (((fnr_reg & USB_FNR_RXDP) != 0U) || ((istr_reg & USB_ISTR_LS_DCONN) != 0U)) {
+ _hcd_data.connected = false;
+ hcd_event_device_remove(rhport, in_isr);
+ }
+ }
+}
+
+// Handle ACK response
+static void ch_handle_ack(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) {
+ uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD;
+ uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos;
+
+ uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0));
+ if (ep_id == TUSB_INDEX_INVALID_8) return;
+
+ hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id];
+ hcd_channel_t* channel = &_hcd_data.channel[ch_id];
+
+ if (dir == TUSB_DIR_OUT) {
+ // OUT/TX direction
+ if (edpt->buflen != edpt->queued_len) {
+ // More data to send
+ uint16_t const len = tu_min16(edpt->buflen - edpt->queued_len, edpt->max_packet_size);
+ uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_TX);
+ fsdev_write_packet_memory(pma_addr, &(edpt->buffer[edpt->queued_len]), len);
+ btable_set_count(ch_id, BTABLE_BUF_TX, len);
+ edpt->queued_len += len;
+ channel_write_status(ch_id, ch_reg, TUSB_DIR_OUT, EP_STAT_VALID, false);
+ channel->out.nak = 0;
+ } else {
+ // Transfer complete
+ channel_dealloc(channel, TUSB_DIR_OUT);
+ edpt->pid = (ch_reg & USB_CHEP_DTOG_TX) ? 1 : 0;
+ hcd_event_xfer_complete(daddr, ep_num, edpt->queued_len, XFER_RESULT_SUCCESS, true);
+ }
+ } else {
+ // IN/RX direction
+ uint16_t const rx_count = channel_get_rx_count(ch_id);
+ uint16_t pma_addr = (uint16_t) btable_get_addr(ch_id, BTABLE_BUF_RX);
+
+ fsdev_read_packet_memory(edpt->buffer + edpt->queued_len, pma_addr, rx_count);
+ edpt->queued_len += rx_count;
+
+ if ((rx_count < edpt->max_packet_size) || (edpt->queued_len >= edpt->buflen)) {
+ // Transfer complete (short packet or all bytes received)
+ channel_dealloc(channel, TUSB_DIR_IN);
+ edpt->pid = (ch_reg & USB_CHEP_DTOG_RX) ? 1 : 0;
+ hcd_event_xfer_complete(daddr, ep_num | TUSB_DIR_IN_MASK, edpt->queued_len, XFER_RESULT_SUCCESS, true);
+ } else {
+ // More data expected
+ uint16_t const cnt = tu_min16(edpt->buflen - edpt->queued_len, edpt->max_packet_size);
+ btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, cnt);
+ channel_write_status(ch_id, ch_reg, TUSB_DIR_IN, EP_STAT_VALID, false);
+ channel->in.nak = 0;
+ }
+ }
+}
+
+// Handle NAK response
+static void ch_handle_nak(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) {
+ uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD;
+ uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos;
+
+ uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0));
+ if (ep_id == TUSB_INDEX_INVALID_8) return;
+
+ hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id];
+ // Retry non-periodic transfer immediately if NAK count not exceeded
+ // Periodic transfer will be retried by next frame automatically
+ if (edpt->ep_type == TUSB_XFER_CONTROL || edpt->ep_type == TUSB_XFER_BULK) {
+ hcd_channel_dir_t* channel_dir =
+ (dir == TUSB_DIR_OUT) ? &(_hcd_data.channel[ch_id].out) : &(_hcd_data.channel[ch_id].in);
+ if (channel_dir->nak < HCD_XFER_NAK_MAX) {
+ channel_dir->nak++;
+ }
+ if (channel_dir->nak < _tuh_cfg.max_nak || _tuh_cfg.max_nak == 0) {
+ channel_write_status(ch_id, ch_reg, dir, EP_STAT_VALID, false);
+ }
+ }
+}
+
+// Handle STALL response
+static void ch_handle_stall(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) {
+ uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD;
+ uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos;
+
+ uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0));
+ if (ep_id == TUSB_INDEX_INVALID_8) return;
+
+ hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id];
+ hcd_channel_t* channel = &_hcd_data.channel[ch_id];
+ channel_dealloc(channel, dir);
+
+ channel_write_status(ch_id, ch_reg, dir, EP_STAT_DISABLED, false);
+
+ hcd_event_xfer_complete(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0),
+ edpt->queued_len, XFER_RESULT_STALLED, true);
+}
+
+// Handle error response
+static void ch_handle_error(uint8_t ch_id, uint32_t ch_reg, tusb_dir_t dir) {
+ uint8_t const ep_num = ch_reg & USB_EPADDR_FIELD;
+ uint8_t const daddr = (ch_reg & USB_CHEP_DEVADDR_Msk) >> USB_CHEP_DEVADDR_Pos;
+
+ uint8_t ep_id = endpoint_find(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0));
+ if (ep_id == TUSB_INDEX_INVALID_8) return;
+
+ hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id];
+ hcd_channel_t* channel = &_hcd_data.channel[ch_id];
+
+ ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir);
+ ch_reg &= ~(dir == TUSB_DIR_OUT ? USB_CH_ERRTX : USB_CH_ERRRX);
+
+ hcd_channel_dir_t* channel_dir =
+ (dir == TUSB_DIR_OUT) ? &(_hcd_data.channel[ch_id].out) : &(_hcd_data.channel[ch_id].in);
+ if (channel_dir->retry < HCD_XFER_ERROR_MAX) {
+ // Retry
+ channel_dir->retry++;
+ ch_change_status(&ch_reg, dir, EP_STAT_VALID);
+ } else {
+ // Failed after retries
+ channel_dealloc(channel, dir);
+ ch_change_status(&ch_reg, dir, EP_STAT_DISABLED);
+ hcd_event_xfer_complete(daddr, ep_num | (dir == TUSB_DIR_IN ? TUSB_DIR_IN_MASK : 0),
+ edpt->queued_len, XFER_RESULT_FAILED, true);
+ }
+ ch_write(ch_id, ch_reg, false);
+}
+
+// Handle CTR interrupt for the TX/OUT direction
+static inline void handle_ctr_tx(uint32_t ch_id) {
+ uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX;
+ hcd_channel_t* channel = &_hcd_data.channel[ch_id];
+ TU_VERIFY(channel->out.allocated == 1,);
+
+ if ((ch_reg & USB_CH_ERRTX) == 0U) {
+ // No error
+ if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_ACK_SBUF) {
+ ch_handle_ack(ch_id, ch_reg, TUSB_DIR_OUT);
+ } else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_NAK) {
+ ch_handle_nak(ch_id, ch_reg, TUSB_DIR_OUT);
+ } else if ((ch_reg & USB_CH_TX_STTX) == USB_CH_TX_STALL) {
+ ch_handle_stall(ch_id, ch_reg, TUSB_DIR_OUT);
+ }
+ } else {
+ ch_handle_error(ch_id, ch_reg, TUSB_DIR_OUT);
+ }
+}
+
+// Handle CTR interrupt for the RX/IN direction
+static inline void handle_ctr_rx(uint32_t ch_id) {
+ uint32_t ch_reg = ch_read(ch_id) | USB_EP_CTR_TX | USB_EP_CTR_RX;
+ hcd_channel_t* channel = &_hcd_data.channel[ch_id];
+ TU_VERIFY(channel->in.allocated == 1,);
+
+ if ((ch_reg & USB_CH_ERRRX) == 0U) {
+ // No error
+ if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_ACK_SBUF) {
+ ch_handle_ack(ch_id, ch_reg, TUSB_DIR_IN);
+ } else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_NAK) {
+ ch_handle_nak(ch_id, ch_reg, TUSB_DIR_IN);
+ } else if ((ch_reg & USB_CH_RX_STRX) == USB_CH_RX_STALL){
+ ch_handle_stall(ch_id, ch_reg, TUSB_DIR_IN);
+ }
+ } else {
+ ch_handle_error(ch_id, ch_reg, TUSB_DIR_IN);
+ }
+}
+
+// Interrupt Handler
+void hcd_int_handler(uint8_t rhport, bool in_isr) {
+ uint32_t int_status = FSDEV_REG->ISTR;
+
+ // Start of Frame
+ if (int_status & USB_ISTR_SOF) {
+ FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_SOF;
+ sof_handler();
+ }
+
+ // Port Change Detected (Connection/Disconnection)
+ if (int_status & USB_ISTR_DCON) {
+ FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_DCON;
+ port_status_handler(rhport, in_isr);
+ }
+
+ // Handle transfer complete (CTR)
+ while (FSDEV_REG->ISTR & USB_ISTR_CTR) {
+ uint32_t const ch_id = FSDEV_REG->ISTR & USB_ISTR_EP_ID;
+ uint32_t const ch_reg = ch_read(ch_id);
+
+ if (ch_reg & USB_EP_CTR_RX) {
+ ch_write_clear_ctr(ch_id, TUSB_DIR_IN);
+ handle_ctr_rx(ch_id);
+ }
+
+ if (ch_reg & USB_EP_CTR_TX) {
+ ch_write_clear_ctr(ch_id, TUSB_DIR_OUT);
+ handle_ctr_tx(ch_id);
+ }
+ }
+
+ if (int_status & USB_ISTR_ERR) {
+ FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_ERR;
+ // TODO: Handle error
+ }
+
+ if (int_status & USB_ISTR_PMAOVR) {
+ TU_BREAKPOINT();
+ FSDEV_REG->ISTR = (fsdev_bus_t)~USB_ISTR_PMAOVR;
+ }
+}
+
+// Enable USB interrupt
+void hcd_int_enable(uint8_t rhport) {
+ fsdev_int_enable(rhport);
+}
+
+// Disable USB interrupt
+void hcd_int_disable(uint8_t rhport) {
+ fsdev_int_disable(rhport);
+}
+
+// Get frame number (1ms)
+uint32_t hcd_frame_number(uint8_t rhport) {
+ (void) rhport;
+ return FSDEV_REG->FNR & USB_FNR_FN;
+}
+
+//--------------------------------------------------------------------+
+// Port API
+//--------------------------------------------------------------------+
+
+// Get the current connect status of roothub port
+bool hcd_port_connect_status(uint8_t rhport) {
+ (void) rhport;
+ return _hcd_data.connected;
+}
+
+// Reset USB bus on the port
+void hcd_port_reset(uint8_t rhport) {
+ (void) rhport;
+ FSDEV_REG->CNTR |= USB_CNTR_FRES;
+}
+
+// Complete bus reset sequence
+void hcd_port_reset_end(uint8_t rhport) {
+ (void) rhport;
+ FSDEV_REG->CNTR &= ~USB_CNTR_FRES;
+}
+
+// Get port link speed
+tusb_speed_t hcd_port_speed_get(uint8_t rhport) {
+ (void) rhport;
+ if ((FSDEV_REG->ISTR & USB_ISTR_LS_DCONN) != 0U) {
+ return TUSB_SPEED_LOW;
+ } else {
+ return TUSB_SPEED_FULL;
+ }
+}
+
+// HCD closes all opened endpoints belonging to this device
+void hcd_device_close(uint8_t rhport, uint8_t dev_addr) {
+ (void) rhport;
+
+ // Close all endpoints for this device
+ for(uint32_t i = 0; i < CFG_TUH_FSDEV_ENDPOINT_MAX; i++) {
+ hcd_endpoint_t* edpt = &_hcd_data.edpt[i];
+ if (edpt->allocated == 1 && edpt->dev_addr == dev_addr) {
+ edpoint_close(i);
+ }
+ }
+
+}
+
+//--------------------------------------------------------------------+
+// Endpoints API
+//--------------------------------------------------------------------+
+
+// Open an endpoint
+bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const *ep_desc) {
+ (void) rhport;
+
+ uint8_t const ep_addr = ep_desc->bEndpointAddress;
+ uint16_t const packet_size = tu_edpt_packet_size(ep_desc);
+ uint8_t const ep_type = ep_desc->bmAttributes.xfer;
+
+ uint8_t const ep_id = endpoint_alloc();
+ TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8);
+
+ hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id];
+ edpt->dev_addr = dev_addr;
+ edpt->ep_addr = ep_addr;
+ edpt->ep_type = ep_type;
+ edpt->max_packet_size = packet_size;
+ edpt->interval = ep_desc->bInterval;
+ edpt->pid = 0;
+ edpt->ls_pre = (hcd_port_speed_get(rhport) == TUSB_SPEED_FULL && tuh_speed_get(dev_addr) == TUSB_SPEED_LOW) ? 1 : 0;
+
+ return true;
+}
+
+bool hcd_edpt_close(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ (void) rhport;
+
+ uint8_t const ep_id = endpoint_find(dev_addr, ep_addr);
+ TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8);
+
+ edpoint_close(ep_id);
+
+ return true;
+}
+
+// Submit a transfer
+bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *buffer, uint16_t buflen) {
+ (void) rhport;
+
+ TU_LOG(FSDEV_DEBUG, "hcd_edpt_xfer addr=%u ep=0x%02X len=%u\r\n", dev_addr, ep_addr, buflen);
+
+ uint8_t const ep_id = endpoint_find(dev_addr, ep_addr);
+ TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8);
+
+ hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id];
+
+ edpt->buffer = buffer;
+ edpt->buflen = buflen;
+ edpt->queued_len = 0;
+
+ uint8_t const ep_num = tu_edpt_number(ep_addr);
+ if (ep_num == 0) {
+ // update ep_dir since control endpoint can switch direction
+ edpt->ep_addr = ep_addr;
+ }
+
+ return edpt_xfer_kickoff(ep_id);
+}
+
+// Abort a queued transfer
+bool hcd_edpt_abort_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr) {
+ (void) rhport;
+
+ uint8_t const ep_id = endpoint_find(dev_addr, ep_addr);
+ TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8);
+ tusb_dir_t const dir = tu_edpt_dir(ep_addr);
+
+ for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) {
+ hcd_channel_t* channel = &_hcd_data.channel[i];
+ uint8_t const allocated = (dir == TUSB_DIR_OUT) ? channel->out.allocated : channel->in.allocated;
+
+ if (allocated == 1 &&
+ channel->dev_addr == dev_addr &&
+ channel->ep_num == tu_edpt_number(ep_addr)) {
+ channel_dealloc(channel, dir);
+ uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX;
+ channel_write_status(i, ch_reg, dir, EP_STAT_DISABLED, true);
+ }
+ }
+
+ return true;
+}
+
+// Submit a special transfer to send 8-byte Setup Packet
+bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) {
+ (void) rhport;
+
+ uint8_t const ep_id = endpoint_find(dev_addr, 0);
+ TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8);
+
+ hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id];
+ edpt->next_setup = true;
+ edpt->pid = 0;
+
+ return hcd_edpt_xfer(rhport, dev_addr, 0, (uint8_t*)(uintptr_t) setup_packet, 8);
+}
+
+// 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;
+
+ uint8_t const ep_id = endpoint_find(dev_addr, 0);
+ TU_ASSERT(ep_id != TUSB_INDEX_INVALID_8);
+
+ hcd_endpoint_t *edpt = &_hcd_data.edpt[ep_id];
+ edpt->pid = 0;
+
+ return true;
+}
+
+//--------------------------------------------------------------------+
+// Helper Functions
+//--------------------------------------------------------------------+
+
+static uint8_t endpoint_alloc(void) {
+ for (uint32_t i = 0; i < CFG_TUH_FSDEV_ENDPOINT_MAX; i++) {
+ hcd_endpoint_t* edpt = &_hcd_data.edpt[i];
+ if (edpt->allocated == 0) {
+ edpt->allocated = 1;
+ return i;
+ }
+ }
+ return TUSB_INDEX_INVALID_8;
+}
+
+static uint8_t endpoint_find(uint8_t dev_addr, uint8_t ep_addr) {
+ uint8_t const ep_num = tu_edpt_number(ep_addr);
+ tusb_dir_t const ep_dir = tu_edpt_dir(ep_addr);
+
+ for (uint32_t i = 0; i < (uint32_t)CFG_TUH_FSDEV_ENDPOINT_MAX; i++) {
+ hcd_endpoint_t* edpt = &_hcd_data.edpt[i];
+ tusb_dir_t const dir = tu_edpt_dir(edpt->ep_addr);
+ uint8_t const num = tu_edpt_number(edpt->ep_addr);
+ // Match both ep_num and ep_dir, or match ep_num 0 (control endpoint)
+ if (edpt->allocated == 1 && edpt->dev_addr == dev_addr && num == ep_num &&
+ (dir == ep_dir || ep_num == 0)) {
+ return i;
+ }
+ }
+ return TUSB_INDEX_INVALID_8;
+}
+
+// close an opened endpoint
+static void edpoint_close(uint8_t ep_id) {
+ hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id];
+ endpoint_dealloc(edpt);
+
+ // disable active channel belong to this endpoint
+ for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) {
+ hcd_channel_t* channel = &_hcd_data.channel[i];
+ uint32_t ch_reg = ch_read(i) | USB_EP_CTR_TX | USB_EP_CTR_RX;
+ if (channel->out.allocated == 1 && channel->out.edpt == edpt) {
+ channel_dealloc(channel, TUSB_DIR_OUT);
+ channel_write_status(i, ch_reg, TUSB_DIR_OUT, EP_STAT_DISABLED, true);
+ }
+ if (channel->in.allocated == 1 && channel->in.edpt == edpt) {
+ channel_dealloc(channel, TUSB_DIR_IN);
+ channel_write_status(i, ch_reg, TUSB_DIR_IN, EP_STAT_DISABLED, true);
+ }
+ }
+}
+
+// Allocate PMA buffer
+static uint32_t hcd_pma_alloc(uint8_t channel, tusb_dir_t dir, uint16_t len) {
+ (void) len;
+ // Simple static allocation as we are unlikely to handle ISO endpoints in host mode
+ // We just give each channel two buffers of max packet size (64 bytes) for IN and OUT
+
+ uint16_t addr = FSDEV_BTABLE_BASE + 8 * FSDEV_EP_COUNT;
+ addr += channel * TUSB_EPSIZE_BULK_FS * 2 + (dir == TUSB_DIR_IN ? TUSB_EPSIZE_BULK_FS : 0);
+
+ TU_ASSERT(addr <= FSDEV_PMA_SIZE, 0xFFFF);
+
+ return addr;
+}
+
+// Allocate hardware channel
+static uint8_t channel_alloc(uint8_t dev_addr, uint8_t ep_addr, uint8_t ep_type) {
+ uint8_t const ep_num = tu_edpt_number(ep_addr);
+ tusb_dir_t const dir = tu_edpt_dir(ep_addr);
+
+ // Find channel allocate for same ep_num but other direction
+ tusb_dir_t const other_dir = (dir == TUSB_DIR_IN) ? TUSB_DIR_OUT : TUSB_DIR_IN;
+ for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) {
+ uint8_t const allocated_dir = (dir == TUSB_DIR_OUT) ? _hcd_data.channel[i].out.allocated : _hcd_data.channel[i].in.allocated;
+ uint8_t const allocated_other = (other_dir == TUSB_DIR_OUT) ? _hcd_data.channel[i].out.allocated : _hcd_data.channel[i].in.allocated;
+ if (allocated_dir == 0 &&
+ allocated_other == 1 &&
+ _hcd_data.channel[i].dev_addr == dev_addr &&
+ _hcd_data.channel[i].ep_num == ep_num &&
+ _hcd_data.channel[i].ep_type == ep_type) {
+ if (dir == TUSB_DIR_OUT) {
+ _hcd_data.channel[i].out.allocated = 1;
+ _hcd_data.channel[i].out.retry = 0;
+ } else {
+ _hcd_data.channel[i].in.allocated = 1;
+ _hcd_data.channel[i].in.retry = 0;
+ }
+ return i;
+ }
+ }
+
+ // Find free channel
+ for (uint8_t i = 0; i < FSDEV_EP_COUNT; i++) {
+ if (_hcd_data.channel[i].out.allocated == 0 && _hcd_data.channel[i].in.allocated == 0) {
+ _hcd_data.channel[i].dev_addr = dev_addr;
+ _hcd_data.channel[i].ep_num = ep_num;
+ _hcd_data.channel[i].ep_type = ep_type;
+ if (dir == TUSB_DIR_OUT) {
+ _hcd_data.channel[i].out.allocated = 1;
+ _hcd_data.channel[i].out.retry = 0;
+ } else {
+ _hcd_data.channel[i].in.allocated = 1;
+ _hcd_data.channel[i].in.retry = 0;
+ }
+ return i;
+ }
+ }
+
+ // Allocation failed
+ return TUSB_INDEX_INVALID_8;
+}
+
+// kick-off transfer with an endpoint
+static bool edpt_xfer_kickoff(uint8_t ep_id) {
+ hcd_endpoint_t* edpt = &_hcd_data.edpt[ep_id];
+ uint8_t ch_id = channel_alloc(edpt->dev_addr, edpt->ep_addr, edpt->ep_type);
+ TU_ASSERT(ch_id != TUSB_INDEX_INVALID_8); // all channel are in used
+
+ tusb_dir_t const dir = tu_edpt_dir(edpt->ep_addr);
+ hcd_channel_t* channel = &_hcd_data.channel[ch_id];
+ if (dir == TUSB_DIR_OUT) {
+ channel->out.edpt = edpt;
+ } else {
+ channel->in.edpt = edpt;
+ }
+
+ return channel_xfer_start(ch_id, dir);
+}
+
+static bool channel_xfer_start(uint8_t ch_id, tusb_dir_t dir) {
+ hcd_channel_t* channel = &_hcd_data.channel[ch_id];
+ hcd_endpoint_t* edpt = (dir == TUSB_DIR_OUT) ? channel->out.edpt : channel->in.edpt;
+
+ uint32_t ch_reg = ch_read(ch_id) & ~USB_EPREG_MASK;
+ ch_reg |= tu_edpt_number(edpt->ep_addr) | edpt->dev_addr << USB_CHEP_DEVADDR_Pos |
+ USB_EP_CTR_TX | USB_EP_CTR_RX;
+
+ // Set type
+ switch (edpt->ep_type) {
+ case TUSB_XFER_BULK:
+ ch_reg |= USB_EP_BULK;
+ break;
+ case TUSB_XFER_INTERRUPT:
+ ch_reg |= USB_EP_INTERRUPT;
+ break;
+
+ case TUSB_XFER_CONTROL:
+ ch_reg |= USB_EP_CONTROL;
+ break;
+
+ default:
+ // Note: ISO endpoint is unsupported
+ TU_ASSERT(false);
+ }
+
+ /* Create a packet memory buffer area. */
+ uint16_t pma_addr = hcd_pma_alloc(ch_id, dir, edpt->max_packet_size);
+ btable_set_addr(ch_id, dir == TUSB_DIR_OUT ? BTABLE_BUF_TX : BTABLE_BUF_RX, pma_addr);
+
+ if (dir == TUSB_DIR_OUT) {
+ uint16_t const len = tu_min16(edpt->buflen - edpt->queued_len, edpt->max_packet_size);
+
+ fsdev_write_packet_memory(pma_addr, &(edpt->buffer[edpt->queued_len]), len);
+ btable_set_count(ch_id, BTABLE_BUF_TX, len);
+
+ edpt->queued_len += len;
+ } else {
+ btable_set_rx_bufsize(ch_id, BTABLE_BUF_RX, edpt->max_packet_size);
+ }
+
+ if (edpt->ls_pre == 1) {
+ ch_reg |= USB_CHEP_LSEP;
+ } else {
+ ch_reg &= ~USB_CHEP_LSEP;
+ }
+
+ // Setup DATA/STATUS phase start with DATA1
+ if (tu_edpt_number(edpt->ep_addr) == 0) {
+ edpt->pid = 1;
+ }
+
+ if (edpt->next_setup) {
+ edpt->next_setup = false;
+ ch_reg |= USB_EP_SETUP;
+ edpt->pid = 0;
+ }
+
+ ch_change_status(&ch_reg, dir, EP_STAT_VALID);
+ ch_change_dtog(&ch_reg, dir, edpt->pid);
+ ch_reg &= USB_EPREG_MASK | CH_STAT_MASK(dir) | CH_DTOG_MASK(dir);
+ ch_write(ch_id, ch_reg, true);
+
+ return true;
+}
+
+#endif
diff --git a/tools/get_deps.py b/tools/get_deps.py
index 0d9c1a8f1..b1b50d319 100755
--- a/tools/get_deps.py
+++ b/tools/get_deps.py
@@ -144,7 +144,7 @@ deps_optional = {
'stm32h7'],
'hw/mcu/st/stm32-tcpp0203': ['https://github.com/STMicroelectronics/stm32-tcpp0203.git',
'9918655bff176ac3046ccf378b5c7bbbc6a38d15',
- 'stm32h7rs stm32n6'],
+ 'stm32h5 stm32h7rs stm32n6'],
'hw/mcu/st/stm32c0xx_hal_driver': ['https://github.com/STMicroelectronics/stm32c0xx_hal_driver.git',
'c283b143bef6bdaacf64240ee6f15eb61dad6125',
'stm32c0'],
diff --git a/tools/iar_template.ipcf b/tools/iar_template.ipcf
index 2581a4702..caddda826 100644
--- a/tools/iar_template.ipcf
+++ b/tools/iar_template.ipcf
@@ -217,7 +217,9 @@
$TUSB_DIR$/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c
- $TUSB_DIR$/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.h
+ $TUSB_DIR$/src/portable/st/stm32_fsdev/hcd_stm32_fsdev.c
+ $TUSB_DIR$/src/portable/st/stm32_fsdev/fsdev_common.c
+ $TUSB_DIR$/src/portable/st/stm32_fsdev/fsdev_common.h
$TUSB_DIR$/src/portable/st/typec/typec_stm32.c