diff --git a/cores/esp32/esp32-hal-tinyusb.c b/cores/esp32/esp32-hal-tinyusb.c
index 04edd77fa19..ab66e3d8e28 100644
--- a/cores/esp32/esp32-hal-tinyusb.c
+++ b/cores/esp32/esp32-hal-tinyusb.c
@@ -20,6 +20,7 @@
 
 #include "hal/usb_hal.h"
 #include "hal/gpio_ll.h"
+#include "hal/usb_serial_jtag_ll.h"
 
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
@@ -376,6 +377,120 @@ __attribute__ ((weak)) int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_
 static bool usb_persist_enabled = false;
 static restart_type_t usb_persist_mode = RESTART_NO_PERSIST;
 
+#if CONFIG_IDF_TARGET_ESP32S3
+
+static void hw_cdc_reset_handler(void *arg) {
+    portBASE_TYPE xTaskWoken = 0;
+    uint32_t usbjtag_intr_status = usb_serial_jtag_ll_get_intsts_mask();
+    usb_serial_jtag_ll_clr_intsts_mask(usbjtag_intr_status);
+    
+    if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_BUS_RESET) {
+        xSemaphoreGiveFromISR((xSemaphoreHandle)arg, &xTaskWoken);
+    }
+
+    if (xTaskWoken == pdTRUE) {
+        portYIELD_FROM_ISR();
+    }
+}
+
+static void usb_switch_to_cdc_jtag(){
+    // Disable USB-OTG
+    periph_module_reset(PERIPH_USB_MODULE);
+    //periph_module_enable(PERIPH_USB_MODULE);
+    periph_module_disable(PERIPH_USB_MODULE);
+
+    // Switch to hardware CDC+JTAG
+    CLEAR_PERI_REG_MASK(RTC_CNTL_USB_CONF_REG, (RTC_CNTL_SW_HW_USB_PHY_SEL|RTC_CNTL_SW_USB_PHY_SEL|RTC_CNTL_USB_PAD_ENABLE));
+
+    // Do not use external PHY
+    CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_PHY_SEL);
+
+    // Release GPIO pins from  CDC+JTAG
+    CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_USB_PAD_ENABLE);
+
+    // Force the host to re-enumerate (BUS_RESET)
+    pinMode(USBPHY_DM_NUM, OUTPUT_OPEN_DRAIN);
+    pinMode(USBPHY_DP_NUM, OUTPUT_OPEN_DRAIN);
+    digitalWrite(USBPHY_DM_NUM, LOW);
+    digitalWrite(USBPHY_DP_NUM, LOW);
+
+    // Initialize CDC+JTAG ISR to listen for BUS_RESET
+    usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_LL_INTR_MASK);
+    usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_LL_INTR_MASK);
+    usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_BUS_RESET);
+    intr_handle_t intr_handle = NULL;
+    xSemaphoreHandle reset_sem = xSemaphoreCreateBinary();
+    if(reset_sem){
+        if(esp_intr_alloc(ETS_USB_SERIAL_JTAG_INTR_SOURCE, 0, hw_cdc_reset_handler, reset_sem, &intr_handle) != ESP_OK){
+            vSemaphoreDelete(reset_sem);
+            reset_sem = NULL;
+            log_e("HW USB CDC failed to init interrupts");
+        }
+    } else {
+        log_e("reset_sem init failed");
+    }
+
+    // Connect GPIOs to integrated CDC+JTAG
+    SET_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_USB_PAD_ENABLE);
+
+    // Wait for BUS_RESET to give us back the semaphore
+    if(reset_sem){
+        if(xSemaphoreTake(reset_sem, 1000 / portTICK_PERIOD_MS) != pdPASS){
+            log_e("reset_sem timeout");
+        }
+        usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_LL_INTR_MASK);
+        esp_intr_free(intr_handle);
+        vSemaphoreDelete(reset_sem);
+    }
+}
+#endif
+
+static void IRAM_ATTR usb_persist_shutdown_handler(void)
+{
+    if(usb_persist_mode != RESTART_NO_PERSIST){
+        if (usb_persist_enabled) {
+            usb_dc_prepare_persist();
+        }
+        if (usb_persist_mode == RESTART_BOOTLOADER) {
+            //USB CDC Download
+            if (usb_persist_enabled) {
+                chip_usb_set_persist_flags(USBDC_PERSIST_ENA);
+#if CONFIG_IDF_TARGET_ESP32S2
+            } else {
+                periph_module_reset(PERIPH_USB_MODULE);
+                periph_module_enable(PERIPH_USB_MODULE);
+#endif
+            }
+            REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
+        } else if (usb_persist_mode == RESTART_BOOTLOADER_DFU) {
+            //DFU Download
+#if CONFIG_IDF_TARGET_ESP32S2
+            // Reset USB Core
+            USB0.grstctl |= USB_CSFTRST;
+            while ((USB0.grstctl & USB_CSFTRST) == USB_CSFTRST){}
+#endif
+            chip_usb_set_persist_flags(USBDC_BOOT_DFU);
+            REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
+        } else if (usb_persist_enabled) {
+            //USB Persist reboot
+            chip_usb_set_persist_flags(USBDC_PERSIST_ENA);
+        }
+    }
+}
+
+void usb_persist_restart(restart_type_t mode)
+{
+    if (mode < RESTART_TYPE_MAX && esp_register_shutdown_handler(usb_persist_shutdown_handler) == ESP_OK) {
+        usb_persist_mode = mode;
+#if CONFIG_IDF_TARGET_ESP32S3
+        if (mode == RESTART_BOOTLOADER) {
+            usb_switch_to_cdc_jtag();
+        }
+#endif
+        esp_restart();
+    }
+}
+
 static bool tinyusb_reserve_in_endpoint(uint8_t endpoint){
     if(endpoint > 6 || (tinyusb_endpoints.in & BIT(endpoint)) != 0){
         return false;
@@ -521,60 +636,6 @@ static void tinyusb_apply_device_config(tinyusb_device_config_t *config){
     tinyusb_device_descriptor.bDeviceProtocol = config->usb_protocol;
 }
 
-static void IRAM_ATTR usb_persist_shutdown_handler(void)
-{
-    if(usb_persist_mode != RESTART_NO_PERSIST){
-        if (usb_persist_enabled) {
-            usb_dc_prepare_persist();
-        }
-        if (usb_persist_mode == RESTART_BOOTLOADER) {
-            //USB CDC Download
-            if (usb_persist_enabled) {
-                chip_usb_set_persist_flags(USBDC_PERSIST_ENA);
-            } else {
-#if CONFIG_IDF_TARGET_ESP32S3
-                /*
-                 * This currently does not work!
-                 * Integrated CDC+JTAG refuses to communicate, once into Download mode
-                */
-                // Disable USB-OTG
-                periph_module_reset(PERIPH_USB_MODULE);
-                //periph_module_enable(PERIPH_USB_MODULE);
-                periph_module_disable(PERIPH_USB_MODULE);
-                // Switch to hardware CDC+JTAG
-                REG_CLR_BIT(RTC_CNTL_USB_CONF_REG, (RTC_CNTL_SW_HW_USB_PHY_SEL|RTC_CNTL_SW_USB_PHY_SEL));
-                // Release GPIO pins from  CDC+JTAG
-                CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_USB_PAD_ENABLE);
-                // Force the host to re-enumerate (BUS_RESET)
-                pinMode(USBPHY_DM_NUM, OUTPUT_OPEN_DRAIN);
-                pinMode(USBPHY_DP_NUM, OUTPUT_OPEN_DRAIN);
-                digitalWrite(USBPHY_DM_NUM, LOW);
-                digitalWrite(USBPHY_DP_NUM, LOW);
-                delay(20);
-                // Connect GPIOs to integrated CDC+JTAG
-                SET_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_USB_PAD_ENABLE);
-                // Do not use external PHY
-                CLEAR_PERI_REG_MASK(USB_SERIAL_JTAG_CONF0_REG, USB_SERIAL_JTAG_PHY_SEL);
-#else
-                periph_module_reset(PERIPH_USB_MODULE);
-                periph_module_enable(PERIPH_USB_MODULE);
-#endif
-            }
-            REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
-        } else if (usb_persist_mode == RESTART_BOOTLOADER_DFU) {
-            //DFU Download
-            // Reset USB Core
-            USB0.grstctl |= USB_CSFTRST;
-            while ((USB0.grstctl & USB_CSFTRST) == USB_CSFTRST){}
-            chip_usb_set_persist_flags(USBDC_BOOT_DFU);
-            REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
-        } else if (usb_persist_enabled) {
-            //USB Persist reboot
-            chip_usb_set_persist_flags(USBDC_PERSIST_ENA);
-        }
-    }
-}
-
 // USB Device Driver task
 // This top level thread processes all usb events and invokes callbacks
 static void usb_device_task(void *param) {
@@ -638,11 +699,6 @@ esp_err_t tinyusb_init(tinyusb_device_config_t *config) {
         periph_module_enable(PERIPH_USB_MODULE);
     }
 
-    if (esp_register_shutdown_handler(usb_persist_shutdown_handler) != ESP_OK) {
-        tinyusb_is_initialized = false;
-        return ESP_FAIL;
-    }
-
     tinyusb_config_t tusb_cfg = {
             .external_phy = false // In the most cases you need to use a `false` value
     };
@@ -655,14 +711,6 @@ esp_err_t tinyusb_init(tinyusb_device_config_t *config) {
     return err;
 }
 
-void usb_persist_restart(restart_type_t mode)
-{
-    if (mode < RESTART_TYPE_MAX) {
-        usb_persist_mode = mode;
-        esp_restart();
-    }
-}
-
 uint8_t tinyusb_add_string_descriptor(const char * str){
     if(str == NULL || tinyusb_string_descriptor_len >= MAX_STRING_DESCRIPTORS){
         return 0;