summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ports/stm32/Makefile22
-rw-r--r--ports/stm32/main.c21
-rw-r--r--ports/stm32/modmachine.c7
-rw-r--r--ports/stm32/modos.c6
-rw-r--r--ports/stm32/modpyb.c2
-rw-r--r--ports/stm32/mpconfigboard_common.h71
-rw-r--r--ports/stm32/mphalport.c28
-rw-r--r--ports/stm32/mphalport.h8
-rw-r--r--ports/stm32/stm32_it.c39
-rw-r--r--ports/stm32/usb.c4
-rw-r--r--ports/stm32/usbd.c42
-rw-r--r--ports/stm32/usbd_conf.c40
-rw-r--r--ports/stm32/usbd_conf.h4
-rwxr-xr-xtools/ci.sh2
14 files changed, 256 insertions, 40 deletions
diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile
index 8b35c82a2..5105b35b1 100644
--- a/ports/stm32/Makefile
+++ b/ports/stm32/Makefile
@@ -58,7 +58,7 @@ MBOOT_TEXT0_ADDR ?= 0x08000000
include $(TOP)/py/py.mk
include $(TOP)/extmod/extmod.mk
-GIT_SUBMODULES += lib/libhydrogen lib/stm32lib
+GIT_SUBMODULES += lib/libhydrogen lib/stm32lib lib/tinyusb
CROSS_COMPILE ?= arm-none-eabi-
LD_DIR=boards
@@ -110,6 +110,8 @@ INC += -I$(STM32LIB_CMSIS_ABS)/Include
INC += -I$(STM32LIB_HAL_ABS)/Inc
INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/inc
#INC += -I$(USBHOST_DIR)
+INC += -I$(TOP)/lib/tinyusb/src
+INC += -I$(TOP)/shared/tinyusb/
INC += -Ilwip_inc
CFLAGS += $(INC) -Wall -Wpointer-arith -Werror -Wdouble-promotion -Wfloat-conversion -std=gnu99 -nostdlib $(CFLAGS_EXTRA)
@@ -213,6 +215,10 @@ SHARED_SRC_C += $(addprefix shared/,\
runtime/stdout_helpers.c \
runtime/sys_stdio_mphal.c \
timeutils/timeutils.c \
+ tinyusb/mp_usbd.c \
+ tinyusb/mp_usbd_cdc.c \
+ tinyusb/mp_usbd_descriptor.c \
+ tinyusb/mp_usbd_runtime.c \
)
ifeq ($(MICROPY_FLOAT_IMPL),double)
@@ -242,7 +248,9 @@ SRC_C += \
boardctrl.c \
main.c \
stm32_it.c \
+ usbd.c \
usbd_conf.c \
+ usb.c \
usbd_desc.c \
usbd_cdc_interface.c \
usbd_hid_interface.c \
@@ -277,7 +285,6 @@ SRC_C += \
can.c \
fdcan.c \
pyb_can.c \
- usb.c \
eth.c \
eth_phy.c \
gccollect.c \
@@ -460,6 +467,16 @@ USBDEV_SRC_C += $(addprefix $(USBDEV_DIR)/,\
class/src/usbd_msc_scsi.c \
)
+# TinyUSB Stack source
+-include $(TOP)/lib/tinyusb/src/tinyusb.mk
+TINYUSB_SRC_C := $(addprefix lib/tinyusb/, \
+ $(TINYUSB_SRC_C) \
+ src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c \
+ src/portable/synopsys/dwc2/dcd_dwc2.c \
+ src/portable/synopsys/dwc2/dwc2_common.c \
+ src/portable/synopsys/dwc2/hcd_dwc2.c \
+ )
+
ifeq ($(MICROPY_SSL_MBEDTLS),1)
LIB_SRC_C += mbedtls/mbedtls_port.c
endif
@@ -499,6 +516,7 @@ OBJ += $(addprefix $(BUILD)/, $(SHARED_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(DRIVERS_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(HAL_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(USBDEV_SRC_C:.c=.o))
+OBJ += $(addprefix $(BUILD)/, $(TINYUSB_SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_C:.c=.o))
OBJ += $(addprefix $(BUILD)/, $(SRC_CXX:.cpp=.o))
OBJ += $(GEN_PINS_SRC:.c=.o)
diff --git a/ports/stm32/main.c b/ports/stm32/main.c
index 1c59b6479..d56b4c407 100644
--- a/ports/stm32/main.c
+++ b/ports/stm32/main.c
@@ -88,6 +88,11 @@
#include "pyb_can.h"
#include "subghz.h"
+#if MICROPY_HW_TINYUSB_STACK
+#include "usbd_conf.h"
+#include "shared/tinyusb/mp_usbd.h"
+#endif
+
#if MICROPY_PY_THREAD
static pyb_thread_t pyb_thread_main;
#endif
@@ -275,14 +280,12 @@ static bool init_sdcard_fs(void) {
}
}
- #if MICROPY_HW_ENABLE_USB
+ #if MICROPY_HW_ENABLE_USB && !MICROPY_HW_TINYUSB_STACK
if (pyb_usb_storage_medium == PYB_USB_STORAGE_MEDIUM_NONE) {
// if no USB MSC medium is selected then use the SD card
pyb_usb_storage_medium = PYB_USB_STORAGE_MEDIUM_SDCARD;
}
- #endif
- #if MICROPY_HW_ENABLE_USB
// only use SD card as current directory if that's what the USB medium is
if (pyb_usb_storage_medium == PYB_USB_STORAGE_MEDIUM_SDCARD)
#endif
@@ -606,8 +609,13 @@ soft_reset:
#endif
#if MICROPY_HW_ENABLE_USB
+ #if MICROPY_HW_TINYUSB_STACK
+ pyb_usbd_init();
+ mp_usbd_init();
+ #else
pyb_usb_init0();
#endif
+ #endif
#if MICROPY_PY_MACHINE_I2S
machine_i2s_init0();
@@ -631,7 +639,7 @@ soft_reset:
}
#endif
- #if MICROPY_HW_ENABLE_USB
+ #if MICROPY_HW_STM_USB_STACK
// if the SD card isn't used as the USB MSC medium then use the internal flash
if (pyb_usb_storage_medium == PYB_USB_STORAGE_MEDIUM_NONE) {
pyb_usb_storage_medium = PYB_USB_STORAGE_MEDIUM_FLASH;
@@ -665,7 +673,7 @@ soft_reset:
// or whose initialisation can be safely deferred until after running
// boot.py.
- #if MICROPY_HW_ENABLE_USB
+ #if MICROPY_HW_STM_USB_STACK
// init USB device to default setting if it was not already configured
if (!(pyb_usb_flags & PYB_USB_FLAG_USB_MODE_CALLED)) {
#if MICROPY_HW_USB_MSC
@@ -770,6 +778,9 @@ soft_reset_exit:
#else
MP_STATE_PORT(pyb_stdio_uart) = NULL;
#endif
+ #if MICROPY_HW_ENABLE_USB_RUNTIME_DEVICE && MICROPY_HW_TINYUSB_STACK
+ mp_usbd_deinit();
+ #endif
MICROPY_BOARD_END_SOFT_RESET(&state);
diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c
index 8123cd801..c1ac6e086 100644
--- a/ports/stm32/modmachine.c
+++ b/ports/stm32/modmachine.c
@@ -47,6 +47,7 @@
#include "rtc.h"
#include "i2c.h"
#include "spi.h"
+#include "shared/tinyusb/mp_usbd.h"
#if defined(STM32G0)
// G0 has BOR and POR combined
@@ -297,9 +298,13 @@ MP_NORETURN static void mp_machine_reset(void) {
// Activate the bootloader without BOOT* pins.
MP_NORETURN void mp_machine_bootloader(size_t n_args, const mp_obj_t *args) {
- #if MICROPY_HW_ENABLE_USB
+ #if MICROPY_HW_STM_USB_STACK
pyb_usb_dev_deinit();
#endif
+ #if MICROPY_HW_ENABLE_USB_RUNTIME_DEVICE && MICROPY_HW_TINYUSB_STACK
+ mp_usbd_deinit();
+ #endif
+
#if MICROPY_HW_ENABLE_STORAGE
storage_flush();
#endif
diff --git a/ports/stm32/modos.c b/ports/stm32/modos.c
index 7949cf87c..cd918fe71 100644
--- a/ports/stm32/modos.c
+++ b/ports/stm32/modos.c
@@ -52,7 +52,7 @@ bool mp_os_dupterm_is_builtin_stream(mp_const_obj_t stream) {
#if MICROPY_PY_MACHINE_UART
|| type == &machine_uart_type
#endif
- #if MICROPY_HW_ENABLE_USB
+ #if MICROPY_HW_STM_USB_STACK
|| type == &pyb_usb_vcp_type
#endif
;
@@ -64,7 +64,7 @@ void mp_os_dupterm_stream_detached_attached(mp_obj_t stream_detached, mp_obj_t s
uart_attach_to_repl(MP_OBJ_TO_PTR(stream_detached), false);
}
#endif
- #if MICROPY_HW_ENABLE_USB
+ #if MICROPY_HW_STM_USB_STACK
if (mp_obj_get_type(stream_detached) == &pyb_usb_vcp_type) {
usb_vcp_attach_to_repl(MP_OBJ_TO_PTR(stream_detached), false);
}
@@ -75,7 +75,7 @@ void mp_os_dupterm_stream_detached_attached(mp_obj_t stream_detached, mp_obj_t s
uart_attach_to_repl(MP_OBJ_TO_PTR(stream_attached), true);
}
#endif
- #if MICROPY_HW_ENABLE_USB
+ #if MICROPY_HW_STM_USB_STACK
if (mp_obj_get_type(stream_attached) == &pyb_usb_vcp_type) {
usb_vcp_attach_to_repl(MP_OBJ_TO_PTR(stream_attached), true);
}
diff --git a/ports/stm32/modpyb.c b/ports/stm32/modpyb.c
index 3d8696e3c..a985fa39d 100644
--- a/ports/stm32/modpyb.c
+++ b/ports/stm32/modpyb.c
@@ -167,7 +167,7 @@ static const mp_rom_map_elem_t pyb_module_globals_table[] = {
// Deprecated (use network.country instead).
{ MP_ROM_QSTR(MP_QSTR_country), MP_ROM_PTR(&mod_network_country_obj) },
- #if MICROPY_HW_ENABLE_USB
+ #if MICROPY_HW_STM_USB_STACK
{ MP_ROM_QSTR(MP_QSTR_usb_mode), MP_ROM_PTR(&pyb_usb_mode_obj) },
#if MICROPY_HW_USB_HID
{ MP_ROM_QSTR(MP_QSTR_hid_mouse), MP_ROM_PTR(&pyb_usb_hid_mouse_obj) },
diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h
index f36cdec8e..47eb7f036 100644
--- a/ports/stm32/mpconfigboard_common.h
+++ b/ports/stm32/mpconfigboard_common.h
@@ -250,12 +250,50 @@
#error "Old USBD_xxx configuration option used, renamed to MICROPY_HW_USB_xxx"
#endif
+// Select whether TinyUSB or legacy STM stack is used to provide USB.
+#ifndef MICROPY_HW_TINYUSB_STACK
+#define MICROPY_HW_TINYUSB_STACK (0)
+#endif
+
+// Central definition for STM USB stack (when not using TinyUSB)
+#define MICROPY_HW_STM_USB_STACK (MICROPY_HW_ENABLE_USB && !MICROPY_HW_TINYUSB_STACK)
+
+#if MICROPY_HW_TINYUSB_STACK
+#ifndef MICROPY_HW_ENABLE_USBDEV
+#define MICROPY_HW_ENABLE_USBDEV (1)
+#endif
+
+#ifndef MICROPY_HW_USB_CDC
+#define MICROPY_HW_USB_CDC (1)
+#endif
+
+#ifndef MICROPY_HW_ENABLE_USB_RUNTIME_DEVICE
+#define MICROPY_HW_ENABLE_USB_RUNTIME_DEVICE (1) // Support machine.USBDevice
+#endif
+#endif
+
+// Configure maximum number of CDC VCP interfaces, and whether MSC/HID are supported
+#ifndef MICROPY_HW_USB_CDC_NUM
+#define MICROPY_HW_USB_CDC_NUM (1)
+#endif
+#ifndef MICROPY_HW_USB_MSC
+#define MICROPY_HW_USB_MSC (MICROPY_HW_STM_USB_STACK)
+#endif
+#ifndef MICROPY_HW_USB_HID
+#define MICROPY_HW_USB_HID (MICROPY_HW_STM_USB_STACK)
+#endif
+
// Default VID and PID values to use for the USB device. If MICROPY_HW_USB_VID
// is defined by a board then all needed PID options must also be defined. The
// VID and PID can also be set dynamically in pyb.usb_mode().
// Windows needs a different PID to distinguish different device configurations.
#ifndef MICROPY_HW_USB_VID
#define MICROPY_HW_USB_VID (0xf055)
+
+// USB PID for TinyUSB Stack.
+#define MICROPY_HW_USB_PID (0x9802)
+
+// USB PID table for STM USB stack.
#define MICROPY_HW_USB_PID_CDC_MSC (0x9800)
#define MICROPY_HW_USB_PID_CDC_HID (0x9801)
#define MICROPY_HW_USB_PID_CDC (0x9802)
@@ -369,6 +407,8 @@
#endif
#define MICROPY_HW_MAX_LPUART (0)
+#define CFG_TUSB_MCU OPT_MCU_STM32F4
+
// Configuration for STM32F7 series
#elif defined(STM32F7)
@@ -384,6 +424,8 @@
#define MICROPY_HW_MAX_UART (8)
#define MICROPY_HW_MAX_LPUART (0)
+#define CFG_TUSB_MCU OPT_MCU_STM32F7
+
// Configuration for STM32G0 series
#elif defined(STM32G0)
@@ -394,6 +436,8 @@
#define MICROPY_HW_MAX_UART (6)
#define MICROPY_HW_MAX_LPUART (2)
+#define CFG_TUSB_MCU OPT_MCU_STM32G0
+
// Configuration for STM32G4 series
#elif defined(STM32G4)
@@ -404,6 +448,8 @@
#define MICROPY_HW_MAX_UART (5) // UART1-5 + LPUART1
#define MICROPY_HW_MAX_LPUART (1)
+#define CFG_TUSB_MCU OPT_MCU_STM32G4
+
// Configuration for STM32H5 series
#elif defined(STM32H5)
@@ -414,6 +460,8 @@
#define MICROPY_HW_MAX_UART (12)
#define MICROPY_HW_MAX_LPUART (1)
+#define CFG_TUSB_MCU OPT_MCU_STM32H5
+
// Configuration for STM32H7A3/B3 series
#elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || \
defined(STM32H7B3xx) || defined(STM32H7B3xxQ)
@@ -425,6 +473,8 @@
#define MICROPY_HW_MAX_UART (10)
#define MICROPY_HW_MAX_LPUART (1)
+#define CFG_TUSB_MCU OPT_MCU_STM32H7
+
// Configuration for STM32H7 series
#elif defined(STM32H7)
@@ -435,6 +485,8 @@
#define MICROPY_HW_MAX_UART (8)
#define MICROPY_HW_MAX_LPUART (1)
+#define CFG_TUSB_MCU OPT_MCU_STM32H7
+
#if defined(MICROPY_HW_ANALOG_SWITCH_PA0) \
|| defined(MICROPY_HW_ANALOG_SWITCH_PA1) \
|| defined(MICROPY_HW_ANALOG_SWITCH_PC2) \
@@ -454,6 +506,8 @@
#define MICROPY_HW_MAX_UART (5)
#define MICROPY_HW_MAX_LPUART (1)
+#define CFG_TUSB_MCU OPT_MCU_STM32L0
+
// Configuration for STM32L1 series
#elif defined(STM32L1)
#define MP_HAL_UNIQUE_ID_ADDRESS (UID_BASE)
@@ -464,6 +518,8 @@
#define MICROPY_HW_MAX_UART (5)
#define MICROPY_HW_MAX_LPUART (0)
+#define CFG_TUSB_MCU OPT_MCU_STM32L1
+
// Configuration for STM32L4 series
#elif defined(STM32L4)
@@ -474,6 +530,8 @@
#define MICROPY_HW_MAX_UART (5)
#define MICROPY_HW_MAX_LPUART (1)
+#define CFG_TUSB_MCU OPT_MCU_STM32L4
+
// Configuration for STM32N6 series
#elif defined(STM32N6)
@@ -508,6 +566,8 @@
#define MICROPY_HW_MAX_UART (1)
#define MICROPY_HW_MAX_LPUART (1)
+#define CFG_TUSB_MCU OPT_MCU_STM32WB
+
#ifndef MICROPY_HW_STM32WB_FLASH_SYNCRONISATION
#define MICROPY_HW_STM32WB_FLASH_SYNCRONISATION (1)
#endif
@@ -715,17 +775,6 @@
#define MICROPY_HW_USB_IS_MULTI_OTG (1)
#endif
-// Configure maximum number of CDC VCP interfaces, and whether MSC/HID are supported
-#ifndef MICROPY_HW_USB_CDC_NUM
-#define MICROPY_HW_USB_CDC_NUM (1)
-#endif
-#ifndef MICROPY_HW_USB_MSC
-#define MICROPY_HW_USB_MSC (MICROPY_HW_ENABLE_USB)
-#endif
-#ifndef MICROPY_HW_USB_HID
-#define MICROPY_HW_USB_HID (MICROPY_HW_ENABLE_USB)
-#endif
-
// Pin definition header file
#define MICROPY_PIN_DEFS_PORT_H "pin_defs_stm32.h"
diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c
index b13ed0ee1..51fb32ae8 100644
--- a/ports/stm32/mphalport.c
+++ b/ports/stm32/mphalport.c
@@ -8,6 +8,17 @@
#include "usb.h"
#include "uart.h"
+#if MICROPY_HW_TINYUSB_STACK
+#include "shared/tinyusb/mp_usbd_cdc.h"
+
+#ifndef MICROPY_HW_STDIN_BUFFER_LEN
+#define MICROPY_HW_STDIN_BUFFER_LEN 512
+#endif
+
+static uint8_t stdin_ringbuf_array[MICROPY_HW_STDIN_BUFFER_LEN];
+ringbuf_t stdin_ringbuf = { stdin_ringbuf_array, sizeof(stdin_ringbuf_array), 0, 0 };
+#endif
+
// this table converts from HAL_StatusTypeDef to POSIX errno
const byte mp_hal_status_to_errno_table[4] = {
[HAL_OK] = 0,
@@ -26,6 +37,9 @@ MP_NORETURN void mp_hal_raise(HAL_StatusTypeDef status) {
MP_WEAK uintptr_t mp_hal_stdio_poll(uintptr_t poll_flags) {
uintptr_t ret = 0;
+ #if MICROPY_HW_USB_CDC && MICROPY_HW_TINYUSB_STACK
+ ret |= mp_usbd_cdc_poll_interfaces(poll_flags);
+ #endif
if (MP_STATE_PORT(pyb_stdio_uart) != NULL) {
mp_obj_t pyb_stdio_uart = MP_OBJ_FROM_PTR(MP_STATE_PORT(pyb_stdio_uart));
int errcode;
@@ -53,6 +67,13 @@ MP_WEAK int mp_hal_stdin_rx_chr(void) {
if (dupterm_c >= 0) {
return dupterm_c;
}
+ #if MICROPY_HW_USB_CDC && MICROPY_HW_TINYUSB_STACK
+ mp_usbd_cdc_poll_interfaces(0);
+ int c = ringbuf_get(&stdin_ringbuf);
+ if (c != -1) {
+ return c;
+ }
+ #endif
MICROPY_EVENT_POLL_HOOK
}
}
@@ -64,6 +85,13 @@ MP_WEAK mp_uint_t mp_hal_stdout_tx_strn(const char *str, size_t len) {
uart_tx_strn(MP_STATE_PORT(pyb_stdio_uart), str, len);
did_write = true;
}
+ #if MICROPY_HW_USB_CDC && MICROPY_HW_TINYUSB_STACK
+ mp_uint_t cdc_res = mp_usbd_cdc_tx_strn(str, len);
+ if (cdc_res > 0) {
+ did_write = true;
+ ret = MIN(cdc_res, ret);
+ }
+ #endif
#if 0 && defined(USE_HOST_MODE) && MICROPY_HW_HAS_LCD
lcd_print_strn(str, len);
#endif
diff --git a/ports/stm32/mphalport.h b/ports/stm32/mphalport.h
index 4d98ce9f1..098a848fb 100644
--- a/ports/stm32/mphalport.h
+++ b/ports/stm32/mphalport.h
@@ -1,6 +1,8 @@
// We use the ST Cube HAL library for most hardware peripherals
#include STM32_HAL_H
#include "pin.h"
+#include "py/ringbuf.h"
+#include "shared/runtime/interrupt_char.h"
extern uint8_t mp_hal_unique_id_address[12];
@@ -41,6 +43,8 @@ static inline int mp_hal_status_to_neg_errno(HAL_StatusTypeDef status) {
return -mp_hal_status_to_errno_table[status];
}
+extern ringbuf_t stdin_ringbuf;
+
MP_NORETURN void mp_hal_raise(HAL_StatusTypeDef status);
void mp_hal_set_interrupt_char(int c); // -1 to disable
@@ -148,3 +152,7 @@ enum {
void mp_hal_generate_laa_mac(int idx, uint8_t buf[6]);
void mp_hal_get_mac(int idx, uint8_t buf[6]);
void mp_hal_get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest);
+
+static inline void mp_hal_wake_main_task_from_isr(void) {
+ // Defined for tinyusb support, nothing needs to be done here.
+}
diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c
index 470df4758..19778020d 100644
--- a/ports/stm32/stm32_it.c
+++ b/ports/stm32/stm32_it.c
@@ -80,7 +80,13 @@
#include "uart.h"
#include "storage.h"
#include "dma.h"
+
+#if MICROPY_HW_TINYUSB_STACK
+#include "tusb.h"
+#include "shared/tinyusb/mp_usbd.h"
+#else
#include "usb.h"
+#endif
#if defined(MICROPY_HW_USB_FS)
extern PCD_HandleTypeDef pcd_fs_handle;
@@ -145,7 +151,7 @@ void HardFault_C_Handler(ExceptionRegisters_t *regs) {
powerctrl_mcu_reset();
}
- #if MICROPY_HW_ENABLE_USB
+ #if MICROPY_HW_STM_USB_STACK
// We need to disable the USB so it doesn't try to write data out on
// the VCP and then block indefinitely waiting for the buffer to drain.
pyb_usb_flags = 0;
@@ -299,7 +305,11 @@ void DebugMon_Handler(void) {
#if MICROPY_HW_USB_FS
void USB_UCPD1_2_IRQHandler(void) {
+ #if MICROPY_HW_TINYUSB_STACK
+ tud_int_handler(0);
+ #else
HAL_PCD_IRQHandler(&pcd_fs_handle);
+ #endif
}
#endif
@@ -307,7 +317,11 @@ void USB_UCPD1_2_IRQHandler(void) {
#if MICROPY_HW_USB_FS
void USB_DRD_FS_IRQHandler(void) {
+ #if MICROPY_HW_TINYUSB_STACK
+ tud_int_handler(0);
+ #else
HAL_PCD_IRQHandler(&pcd_fs_handle);
+ #endif
}
#endif
@@ -315,7 +329,11 @@ void USB_DRD_FS_IRQHandler(void) {
#if MICROPY_HW_USB_FS
void USB_IRQHandler(void) {
+ #if MICROPY_HW_TINYUSB_STACK
+ tud_int_handler(0);
+ #else
HAL_PCD_IRQHandler(&pcd_fs_handle);
+ #endif
}
#endif
@@ -323,7 +341,11 @@ void USB_IRQHandler(void) {
#if MICROPY_HW_USB_FS
void USB_LP_IRQHandler(void) {
+ #if MICROPY_HW_TINYUSB_STACK
+ tud_int_handler(0);
+ #else
HAL_PCD_IRQHandler(&pcd_fs_handle);
+ #endif
}
#endif
@@ -337,7 +359,11 @@ void USB_LP_IRQHandler(void) {
#if MICROPY_HW_USB_FS
void OTG_FS_IRQHandler(void) {
IRQ_ENTER(OTG_FS_IRQn);
+ #if MICROPY_HW_TINYUSB_STACK
+ tud_int_handler(0);
+ #else
HAL_PCD_IRQHandler(&pcd_fs_handle);
+ #endif
IRQ_EXIT(OTG_FS_IRQn);
}
#endif
@@ -345,13 +371,21 @@ void OTG_FS_IRQHandler(void) {
#if defined(STM32N6)
void USB1_OTG_HS_IRQHandler(void) {
IRQ_ENTER(USB1_OTG_HS_IRQn);
+ #if MICROPY_HW_TINYUSB_STACK
+ tud_int_handler(0);
+ #else
HAL_PCD_IRQHandler(&pcd_hs_handle);
+ #endif
IRQ_EXIT(USB1_OTG_HS_IRQn);
}
#else
void OTG_HS_IRQHandler(void) {
IRQ_ENTER(OTG_HS_IRQn);
+ #if MICROPY_HW_TINYUSB_STACK
+ tud_int_handler(0);
+ #else
HAL_PCD_IRQHandler(&pcd_hs_handle);
+ #endif
IRQ_EXIT(OTG_HS_IRQn);
}
#endif
@@ -414,6 +448,9 @@ static void OTG_CMD_WKUP_Handler(PCD_HandleTypeDef *pcd_handle) {
/* ungate PHY clock */
__HAL_PCD_UNGATE_PHYCLOCK(pcd_handle);
}
+ #if MICROPY_HW_TINYUSB_STACK
+ tud_int_handler(0);
+ #endif
}
#endif
diff --git a/ports/stm32/usb.c b/ports/stm32/usb.c
index 81025e48b..15d563713 100644
--- a/ports/stm32/usb.c
+++ b/ports/stm32/usb.c
@@ -45,7 +45,7 @@
#include "sdcard.h"
#include "usb.h"
-#if MICROPY_HW_ENABLE_USB
+#if MICROPY_HW_STM_USB_STACK
// Work out which USB device to use as the main one (the one with the REPL)
#if !defined(MICROPY_HW_USB_MAIN_DEV)
@@ -1156,4 +1156,4 @@ MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_hid_report_desc);
#endif
MP_REGISTER_ROOT_POINTER(mp_obj_t pyb_usb_vcp_irq[MICROPY_HW_USB_CDC_NUM]);
-#endif // MICROPY_HW_ENABLE_USB
+#endif // MICROPY_HW_STM_USB_STACK
diff --git a/ports/stm32/usbd.c b/ports/stm32/usbd.c
new file mode 100644
index 000000000..35275cd1b
--- /dev/null
+++ b/ports/stm32/usbd.c
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the MicroPython project, http://micropython.org/
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2025 Andrew Leech
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "py/mpconfig.h"
+
+#if MICROPY_HW_ENABLE_USBDEV && MICROPY_HW_TINYUSB_STACK
+
+#include "mp_usbd.h"
+#include "py/mpconfig.h"
+#include "string.h"
+#include "mphalport.h"
+
+void mp_usbd_port_get_serial_number(char *serial_buf) {
+ uint8_t *id = (uint8_t *)MP_HAL_UNIQUE_ID_ADDRESS;
+ MP_STATIC_ASSERT(12 * 2 <= MICROPY_HW_USB_DESC_STR_MAX);
+ mp_usbd_hex_str(serial_buf, id, 12);
+}
+
+#endif
diff --git a/ports/stm32/usbd_conf.c b/ports/stm32/usbd_conf.c
index 2cf79e09e..18f350d4a 100644
--- a/ports/stm32/usbd_conf.c
+++ b/ports/stm32/usbd_conf.c
@@ -37,6 +37,12 @@
#if MICROPY_HW_USB_FS || MICROPY_HW_USB_HS
+#if BUILDING_MBOOT
+// TinyUSB not used in mboot
+#undef MICROPY_HW_TINYUSB_STACK
+#endif
+
+// These handles are also used in Interrupt / Wakeup handlers.
#if MICROPY_HW_USB_FS
PCD_HandleTypeDef pcd_fs_handle;
#endif
@@ -56,18 +62,17 @@ PCD_HandleTypeDef pcd_hs_handle;
#define OTG_HS_IRQn USB1_OTG_HS_IRQn
#endif
-/*******************************************************************************
- PCD BSP Routines
-*******************************************************************************/
-
-/**
- * @brief Initializes the PCD MSP.
- * @param hpcd: PCD handle
- * @retval None
- */
-void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
+#if MICROPY_HW_TINYUSB_STACK
+void pyb_usbd_init(void)
+#else
+void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
+#endif
+{
#if MICROPY_HW_USB_FS
- if (hpcd->Instance == USB_OTG_FS) {
+ #if MICROPY_HW_STM_USB_STACK
+ if (hpcd->Instance == USB_OTG_FS)
+ #endif
+ {
// Configure USB GPIO's.
#if defined(STM32G0) || defined(STM32G4)
@@ -139,7 +144,7 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
#endif
// Enable VDDUSB
- #if defined(STM32H5)
+ #if defined(STM32H5) || defined(STM32WB)
HAL_PWREx_EnableVddUSB();
#elif defined(STM32L4)
if (__HAL_RCC_PWR_IS_CLK_DISABLED()) {
@@ -172,12 +177,17 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
HAL_NVIC_EnableIRQ(OTG_FS_IRQn);
#endif
+ #if MICROPY_HW_STM_USB_STACK
return;
+ #endif
}
#endif
#if MICROPY_HW_USB_HS
- if (hpcd->Instance == USB_OTG_HS) {
+ #if MICROPY_HW_STM_USB_STACK
+ if (hpcd->Instance == USB_OTG_HS)
+ #endif
+ {
#if MICROPY_HW_USB_HS_IN_FS
// Configure USB GPIO's.
@@ -319,6 +329,8 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) {
#endif // MICROPY_HW_USB_HS
}
+#if MICROPY_HW_STM_USB_STACK
+
/**
* @brief DeInitializes the PCD MSP.
* @param hpcd: PCD handle
@@ -798,6 +810,8 @@ void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state) {
}
#endif
+#endif // MICROPY_HW_STM_USB_STACK
+
#endif // MICROPY_HW_USB_FS || MICROPY_HW_USB_HS
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/ports/stm32/usbd_conf.h b/ports/stm32/usbd_conf.h
index e61e7ce7e..cb0457982 100644
--- a/ports/stm32/usbd_conf.h
+++ b/ports/stm32/usbd_conf.h
@@ -64,6 +64,10 @@
#define USBD_HS_NUM_TX_FIFO (9)
#define USBD_HS_NUM_FIFO (1 + USBD_HS_NUM_TX_FIFO)
+#if MICROPY_HW_TINYUSB_STACK
+void pyb_usbd_init(void);
+#endif
+
#endif // MICROPY_INCLUDED_STM32_USBD_CONF_H
/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
diff --git a/tools/ci.sh b/tools/ci.sh
index 5d401843b..42d231c45 100755
--- a/tools/ci.sh
+++ b/tools/ci.sh
@@ -511,7 +511,7 @@ function ci_stm32_nucleo_build {
# Test building various MCU families, some with additional options.
make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_F091RC
- make ${MAKEOPTS} -C ports/stm32 BOARD=STM32H573I_DK
+ make ${MAKEOPTS} -C ports/stm32 BOARD=STM32H573I_DK CFLAGS_EXTRA='-DMICROPY_HW_TINYUSB_STACK=1'
make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_H743ZI COPT=-O2 CFLAGS_EXTRA='-DMICROPY_PY_THREAD=1'
make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_L073RZ
make ${MAKEOPTS} -C ports/stm32 BOARD=NUCLEO_L476RG DEBUG=1