diff --git a/cores/esp32/USB.cpp b/cores/esp32/USB.cpp index ce486bcc..6133212f 100644 --- a/cores/esp32/USB.cpp +++ b/cores/esp32/USB.cpp @@ -15,7 +15,6 @@ #include "esp32-hal-tinyusb.h" #include "USB.h" #if CONFIG_USB_ENABLED -#include "usb_persist.h" #ifndef USB_VID #define USB_VID USB_ESPRESSIF_VID diff --git a/cores/esp32/USBCDC.cpp b/cores/esp32/USBCDC.cpp index bd7d4569..01299575 100644 --- a/cores/esp32/USBCDC.cpp +++ b/cores/esp32/USBCDC.cpp @@ -16,7 +16,6 @@ #include "USB.h" #include "USBCDC.h" #if CONFIG_USB_ENABLED -#include "usb_persist.h" ESP_EVENT_DEFINE_BASE(ARDUINO_USB_CDC_EVENTS); esp_err_t arduino_usb_event_post(esp_event_base_t event_base, int32_t event_id, void *event_data, size_t event_data_size, TickType_t ticks_to_wait); diff --git a/cores/esp32/esp32-hal-log.h b/cores/esp32/esp32-hal-log.h index fd4c52d4..57d779cf 100644 --- a/cores/esp32/esp32-hal-log.h +++ b/cores/esp32/esp32-hal-log.h @@ -20,6 +20,7 @@ extern "C" #endif #include "sdkconfig.h" +#include "esp_timer.h" #define ARDUHAL_LOG_LEVEL_NONE (0) #define ARDUHAL_LOG_LEVEL_ERROR (1) diff --git a/cores/esp32/esp32-hal-tinyusb.c b/cores/esp32/esp32-hal-tinyusb.c index ee9abcf9..1ea0b8b1 100644 --- a/cores/esp32/esp32-hal-tinyusb.c +++ b/cores/esp32/esp32-hal-tinyusb.c @@ -29,7 +29,7 @@ #include "esp32-hal.h" #include "esp32-hal-tinyusb.h" -#include "usb_persist.h" +#include "esp32s2/rom/usb/usb_persist.h" typedef char tusb_str_t[127]; @@ -309,6 +309,8 @@ __attribute__ ((weak)) int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_ /* * Private API * */ +static bool usb_persist_enabled = false; +static restart_type_t usb_persist_mode = RESTART_NO_PERSIST; static bool tinyusb_reserve_in_endpoint(uint8_t endpoint){ if(endpoint > 6 || (tinyusb_endpoints.in & BIT(endpoint)) != 0){ @@ -381,7 +383,7 @@ static bool tinyusb_load_enabled_interfaces(){ }; memcpy(tinyusb_config_descriptor, descriptor, TUD_CONFIG_DESC_LEN); if ((tinyusb_loaded_interfaces_mask == (BIT(USB_INTERFACE_CDC) | BIT(USB_INTERFACE_DFU))) || (tinyusb_loaded_interfaces_mask == BIT(USB_INTERFACE_CDC))) { - usb_persist_set_enable(true); + usb_persist_enabled = true; log_d("USB Persist enabled"); } log_d("Load Done: if_num: %u, descr_len: %u, if_mask: 0x%x", tinyusb_loaded_interfaces_num, tinyusb_config_descriptor_len, tinyusb_loaded_interfaces_mask); @@ -451,6 +453,34 @@ 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) { + REG_SET_BIT(RTC_CNTL_USB_CONF_REG, RTC_CNTL_IO_MUX_RESET_DISABLE); + REG_SET_BIT(RTC_CNTL_USB_CONF_REG, RTC_CNTL_USB_RESET_DISABLE); + } + if (usb_persist_mode == RESTART_BOOTLOADER) { + //USB CDC Download + if (usb_persist_enabled) { + USB_WRAP.date.val = USBDC_PERSIST_ENA; + } + REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT); + periph_module_disable(PERIPH_TIMG1_MODULE); + } else if (usb_persist_mode == RESTART_BOOTLOADER_DFU) { + //DFU Download + USB_WRAP.date.val = USBDC_BOOT_DFU; + REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT); + periph_module_disable(PERIPH_TIMG0_MODULE); + periph_module_disable(PERIPH_TIMG1_MODULE); + } else if (usb_persist_enabled) { + //USB Persist reboot + USB_WRAP.date.val = USBDC_PERSIST_ENA; + } + SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST); + } +} + // USB Device Driver task // This top level thread processes all usb events and invokes callbacks static void usb_device_task(void *param) { @@ -488,6 +518,24 @@ esp_err_t tinyusb_init(tinyusb_device_config_t *config) { initialized = false; return ESP_FAIL; } + + bool usb_did_persist = (USB_WRAP.date.val == USBDC_PERSIST_ENA); + + if(usb_did_persist && usb_persist_enabled){ + // Enable USB/IO_MUX peripheral reset, if coming from persistent reboot + REG_CLR_BIT(RTC_CNTL_USB_CONF_REG, RTC_CNTL_IO_MUX_RESET_DISABLE); + REG_CLR_BIT(RTC_CNTL_USB_CONF_REG, RTC_CNTL_USB_RESET_DISABLE); + } else { + // Reset USB module + periph_module_reset(PERIPH_USB_MODULE); + periph_module_enable(PERIPH_USB_MODULE); + } + + if (usb_persist_enabled && esp_register_shutdown_handler(usb_persist_shutdown_handler) != ESP_OK) { + initialized = false; + return ESP_FAIL; + } + tinyusb_config_t tusb_cfg = { .external_phy = false // In the most cases you need to use a `false` value }; @@ -500,6 +548,16 @@ esp_err_t tinyusb_init(tinyusb_device_config_t *config) { return err; } +void usb_persist_restart(restart_type_t mode) +{ + if (usb_persist_enabled && mode < RESTART_TYPE_MAX) { + usb_persist_mode = mode; + esp_restart(); + } else { + log_e("Persistence is not enabled"); + } +} + uint8_t tinyusb_add_string_descriptor(const char * str){ if(str == NULL || tinyusb_string_descriptor_len >= MAX_STRING_DESCRIPTORS){ return 0; diff --git a/cores/esp32/esp32-hal-tinyusb.h b/cores/esp32/esp32-hal-tinyusb.h index 1067a940..3417bb05 100644 --- a/cores/esp32/esp32-hal-tinyusb.h +++ b/cores/esp32/esp32-hal-tinyusb.h @@ -61,6 +61,19 @@ typedef struct { esp_err_t tinyusb_init(tinyusb_device_config_t *config); +/* + * USB Persistence API + * */ +typedef enum { + RESTART_NO_PERSIST, + RESTART_PERSIST, + RESTART_BOOTLOADER, + RESTART_BOOTLOADER_DFU, + RESTART_TYPE_MAX +} restart_type_t; + +void usb_persist_restart(restart_type_t mode); + // The following definitions and functions are to be used only by the drivers typedef enum { USB_INTERFACE_CDC, diff --git a/cores/esp32/esp32-hal.h b/cores/esp32/esp32-hal.h index b22e5922..92bb1828 100644 --- a/cores/esp32/esp32-hal.h +++ b/cores/esp32/esp32-hal.h @@ -20,10 +20,6 @@ #ifndef HAL_ESP32_HAL_H_ #define HAL_ESP32_HAL_H_ -#ifdef __cplusplus -extern "C" { -#endif - #include #include #include @@ -36,6 +32,10 @@ extern "C" { #include "esp_system.h" #include "esp_sleep.h" +#ifdef __cplusplus +extern "C" { +#endif + #ifndef F_CPU #if CONFIG_IDF_TARGET_ESP32 // ESP32/PICO-D4 #define F_CPU (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ * 1000000U)