2020
2121#include "hal/usb_hal.h"
2222#include "hal/gpio_ll.h"
23+ #include "hal/usb_serial_jtag_ll.h"
2324
2425#include "freertos/FreeRTOS.h"
2526#include "freertos/task.h"
@@ -376,6 +377,120 @@ __attribute__ ((weak)) int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_
376377static bool usb_persist_enabled = false;
377378static restart_type_t usb_persist_mode = RESTART_NO_PERSIST ;
378379
380+ #if CONFIG_IDF_TARGET_ESP32S3
381+
382+ static void hw_cdc_reset_handler (void * arg ) {
383+ portBASE_TYPE xTaskWoken = 0 ;
384+ uint32_t usbjtag_intr_status = usb_serial_jtag_ll_get_intsts_mask ();
385+ usb_serial_jtag_ll_clr_intsts_mask (usbjtag_intr_status );
386+
387+ if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_BUS_RESET ) {
388+ xSemaphoreGiveFromISR ((xSemaphoreHandle )arg , & xTaskWoken );
389+ }
390+
391+ if (xTaskWoken == pdTRUE ) {
392+ portYIELD_FROM_ISR ();
393+ }
394+ }
395+
396+ static void usb_switch_to_cdc_jtag (){
397+ // Disable USB-OTG
398+ periph_module_reset (PERIPH_USB_MODULE );
399+ //periph_module_enable(PERIPH_USB_MODULE);
400+ periph_module_disable (PERIPH_USB_MODULE );
401+
402+ // Switch to hardware CDC+JTAG
403+ 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 ));
404+
405+ // Do not use external PHY
406+ CLEAR_PERI_REG_MASK (USB_SERIAL_JTAG_CONF0_REG , USB_SERIAL_JTAG_PHY_SEL );
407+
408+ // Release GPIO pins from CDC+JTAG
409+ CLEAR_PERI_REG_MASK (USB_SERIAL_JTAG_CONF0_REG , USB_SERIAL_JTAG_USB_PAD_ENABLE );
410+
411+ // Force the host to re-enumerate (BUS_RESET)
412+ pinMode (USBPHY_DM_NUM , OUTPUT_OPEN_DRAIN );
413+ pinMode (USBPHY_DP_NUM , OUTPUT_OPEN_DRAIN );
414+ digitalWrite (USBPHY_DM_NUM , LOW );
415+ digitalWrite (USBPHY_DP_NUM , LOW );
416+
417+ // Initialize CDC+JTAG ISR to listen for BUS_RESET
418+ usb_serial_jtag_ll_disable_intr_mask (USB_SERIAL_JTAG_LL_INTR_MASK );
419+ usb_serial_jtag_ll_clr_intsts_mask (USB_SERIAL_JTAG_LL_INTR_MASK );
420+ usb_serial_jtag_ll_ena_intr_mask (USB_SERIAL_JTAG_INTR_BUS_RESET );
421+ intr_handle_t intr_handle = NULL ;
422+ xSemaphoreHandle reset_sem = xSemaphoreCreateBinary ();
423+ if (reset_sem ){
424+ if (esp_intr_alloc (ETS_USB_SERIAL_JTAG_INTR_SOURCE , 0 , hw_cdc_reset_handler , reset_sem , & intr_handle ) != ESP_OK ){
425+ vSemaphoreDelete (reset_sem );
426+ reset_sem = NULL ;
427+ log_e ("HW USB CDC failed to init interrupts" );
428+ }
429+ } else {
430+ log_e ("reset_sem init failed" );
431+ }
432+
433+ // Connect GPIOs to integrated CDC+JTAG
434+ SET_PERI_REG_MASK (USB_SERIAL_JTAG_CONF0_REG , USB_SERIAL_JTAG_USB_PAD_ENABLE );
435+
436+ // Wait for BUS_RESET to give us back the semaphore
437+ if (reset_sem ){
438+ if (xSemaphoreTake (reset_sem , 1000 / portTICK_PERIOD_MS ) != pdPASS ){
439+ log_e ("reset_sem timeout" );
440+ }
441+ usb_serial_jtag_ll_disable_intr_mask (USB_SERIAL_JTAG_LL_INTR_MASK );
442+ esp_intr_free (intr_handle );
443+ vSemaphoreDelete (reset_sem );
444+ }
445+ }
446+ #endif
447+
448+ static void IRAM_ATTR usb_persist_shutdown_handler (void )
449+ {
450+ if (usb_persist_mode != RESTART_NO_PERSIST ){
451+ if (usb_persist_enabled ) {
452+ usb_dc_prepare_persist ();
453+ }
454+ if (usb_persist_mode == RESTART_BOOTLOADER ) {
455+ //USB CDC Download
456+ if (usb_persist_enabled ) {
457+ chip_usb_set_persist_flags (USBDC_PERSIST_ENA );
458+ #if CONFIG_IDF_TARGET_ESP32S2
459+ } else {
460+ periph_module_reset (PERIPH_USB_MODULE );
461+ periph_module_enable (PERIPH_USB_MODULE );
462+ #endif
463+ }
464+ REG_WRITE (RTC_CNTL_OPTION1_REG , RTC_CNTL_FORCE_DOWNLOAD_BOOT );
465+ } else if (usb_persist_mode == RESTART_BOOTLOADER_DFU ) {
466+ //DFU Download
467+ #if CONFIG_IDF_TARGET_ESP32S2
468+ // Reset USB Core
469+ USB0 .grstctl |= USB_CSFTRST ;
470+ while ((USB0 .grstctl & USB_CSFTRST ) == USB_CSFTRST ){}
471+ #endif
472+ chip_usb_set_persist_flags (USBDC_BOOT_DFU );
473+ REG_WRITE (RTC_CNTL_OPTION1_REG , RTC_CNTL_FORCE_DOWNLOAD_BOOT );
474+ } else if (usb_persist_enabled ) {
475+ //USB Persist reboot
476+ chip_usb_set_persist_flags (USBDC_PERSIST_ENA );
477+ }
478+ }
479+ }
480+
481+ void usb_persist_restart (restart_type_t mode )
482+ {
483+ if (mode < RESTART_TYPE_MAX && esp_register_shutdown_handler (usb_persist_shutdown_handler ) == ESP_OK ) {
484+ usb_persist_mode = mode ;
485+ #if CONFIG_IDF_TARGET_ESP32S3
486+ if (mode == RESTART_BOOTLOADER ) {
487+ usb_switch_to_cdc_jtag ();
488+ }
489+ #endif
490+ esp_restart ();
491+ }
492+ }
493+
379494static bool tinyusb_reserve_in_endpoint (uint8_t endpoint ){
380495 if (endpoint > 6 || (tinyusb_endpoints .in & BIT (endpoint )) != 0 ){
381496 return false;
@@ -521,60 +636,6 @@ static void tinyusb_apply_device_config(tinyusb_device_config_t *config){
521636 tinyusb_device_descriptor .bDeviceProtocol = config -> usb_protocol ;
522637}
523638
524- static void IRAM_ATTR usb_persist_shutdown_handler (void )
525- {
526- if (usb_persist_mode != RESTART_NO_PERSIST ){
527- if (usb_persist_enabled ) {
528- usb_dc_prepare_persist ();
529- }
530- if (usb_persist_mode == RESTART_BOOTLOADER ) {
531- //USB CDC Download
532- if (usb_persist_enabled ) {
533- chip_usb_set_persist_flags (USBDC_PERSIST_ENA );
534- } else {
535- #if CONFIG_IDF_TARGET_ESP32S3
536- /*
537- * This currently does not work!
538- * Integrated CDC+JTAG refuses to communicate, once into Download mode
539- */
540- // Disable USB-OTG
541- periph_module_reset (PERIPH_USB_MODULE );
542- //periph_module_enable(PERIPH_USB_MODULE);
543- periph_module_disable (PERIPH_USB_MODULE );
544- // Switch to hardware CDC+JTAG
545- REG_CLR_BIT (RTC_CNTL_USB_CONF_REG , (RTC_CNTL_SW_HW_USB_PHY_SEL |RTC_CNTL_SW_USB_PHY_SEL ));
546- // Release GPIO pins from CDC+JTAG
547- CLEAR_PERI_REG_MASK (USB_SERIAL_JTAG_CONF0_REG , USB_SERIAL_JTAG_USB_PAD_ENABLE );
548- // Force the host to re-enumerate (BUS_RESET)
549- pinMode (USBPHY_DM_NUM , OUTPUT_OPEN_DRAIN );
550- pinMode (USBPHY_DP_NUM , OUTPUT_OPEN_DRAIN );
551- digitalWrite (USBPHY_DM_NUM , LOW );
552- digitalWrite (USBPHY_DP_NUM , LOW );
553- delay (20 );
554- // Connect GPIOs to integrated CDC+JTAG
555- SET_PERI_REG_MASK (USB_SERIAL_JTAG_CONF0_REG , USB_SERIAL_JTAG_USB_PAD_ENABLE );
556- // Do not use external PHY
557- CLEAR_PERI_REG_MASK (USB_SERIAL_JTAG_CONF0_REG , USB_SERIAL_JTAG_PHY_SEL );
558- #else
559- periph_module_reset (PERIPH_USB_MODULE );
560- periph_module_enable (PERIPH_USB_MODULE );
561- #endif
562- }
563- REG_WRITE (RTC_CNTL_OPTION1_REG , RTC_CNTL_FORCE_DOWNLOAD_BOOT );
564- } else if (usb_persist_mode == RESTART_BOOTLOADER_DFU ) {
565- //DFU Download
566- // Reset USB Core
567- USB0 .grstctl |= USB_CSFTRST ;
568- while ((USB0 .grstctl & USB_CSFTRST ) == USB_CSFTRST ){}
569- chip_usb_set_persist_flags (USBDC_BOOT_DFU );
570- REG_WRITE (RTC_CNTL_OPTION1_REG , RTC_CNTL_FORCE_DOWNLOAD_BOOT );
571- } else if (usb_persist_enabled ) {
572- //USB Persist reboot
573- chip_usb_set_persist_flags (USBDC_PERSIST_ENA );
574- }
575- }
576- }
577-
578639// USB Device Driver task
579640// This top level thread processes all usb events and invokes callbacks
580641static void usb_device_task (void * param ) {
@@ -638,11 +699,6 @@ esp_err_t tinyusb_init(tinyusb_device_config_t *config) {
638699 periph_module_enable (PERIPH_USB_MODULE );
639700 }
640701
641- if (esp_register_shutdown_handler (usb_persist_shutdown_handler ) != ESP_OK ) {
642- tinyusb_is_initialized = false;
643- return ESP_FAIL ;
644- }
645-
646702 tinyusb_config_t tusb_cfg = {
647703 .external_phy = false // In the most cases you need to use a `false` value
648704 };
@@ -655,14 +711,6 @@ esp_err_t tinyusb_init(tinyusb_device_config_t *config) {
655711 return err ;
656712}
657713
658- void usb_persist_restart (restart_type_t mode )
659- {
660- if (mode < RESTART_TYPE_MAX ) {
661- usb_persist_mode = mode ;
662- esp_restart ();
663- }
664- }
665-
666714uint8_t tinyusb_add_string_descriptor (const char * str ){
667715 if (str == NULL || tinyusb_string_descriptor_len >= MAX_STRING_DESCRIPTORS ){
668716 return 0 ;
0 commit comments