diff --git a/cpu/esp32/Kconfig.esp32s2 b/cpu/esp32/Kconfig.esp32s2 index 7c0a0c32fe..d27f38ef8b 100644 --- a/cpu/esp32/Kconfig.esp32s2 +++ b/cpu/esp32/Kconfig.esp32s2 @@ -30,6 +30,7 @@ config CPU_FAM_ESP32S2 select MODULE_PTHREAD if MODULE_CPP select MODULE_RTT_RTC if HAS_PERIPH_RTT && MODULE_PERIPH_RTC select MODULE_USBDEV_SYNOPSYS_DWC2 if MODULE_PERIPH_USBDEV + select MODULE_USB_BOARD_RESET if MODULE_USBUS_CDC_ACM || MODULE_TINYUSB_CLASS_CDC imply MODULE_NEWLIB_NANO config CPU_FAM diff --git a/cpu/esp32/Kconfig.esp32s3 b/cpu/esp32/Kconfig.esp32s3 index 53ff34e8c0..99c7316233 100644 --- a/cpu/esp32/Kconfig.esp32s3 +++ b/cpu/esp32/Kconfig.esp32s3 @@ -37,6 +37,7 @@ config CPU_FAM_ESP32S3 select MODULE_PTHREAD if MODULE_CPP select MODULE_RTT_RTC if HAS_PERIPH_RTT && MODULE_PERIPH_RTC select MODULE_USBDEV_SYNOPSYS_DWC2 if MODULE_PERIPH_USBDEV + select MODULE_USB_BOARD_RESET if MODULE_USBUS_CDC_ACM || MODULE_TINYUSB_CLASS_CDC imply MODULE_NEWLIB_NANO config CPU_FAM diff --git a/cpu/esp32/Makefile b/cpu/esp32/Makefile index 1c18ffcba3..91a69869e9 100644 --- a/cpu/esp32/Makefile +++ b/cpu/esp32/Makefile @@ -13,6 +13,10 @@ ifneq (, $(filter esp_bootloader, $(USEMODULE))) DIRS += bootloader endif +ifneq (, $(filter usb_board_reset, $(USEMODULE))) + SRC += usb_reset.c +endif + ifneq (, $(filter esp_ble_nimble, $(USEMODULE))) DIRS += esp-ble-nimble endif diff --git a/cpu/esp32/Makefile.dep b/cpu/esp32/Makefile.dep index 7f12326f49..18bc4421ad 100644 --- a/cpu/esp32/Makefile.dep +++ b/cpu/esp32/Makefile.dep @@ -184,3 +184,10 @@ endif ifneq (,$(filter esp_jtag,$(USEMODULE))) FEATURES_REQUIRED += esp_jtag endif + +# enable bootloader reset over USB, requires CDC ACM to be used +ifneq (,$(filter usbus_cdc_acm tinyusb_class_cdc,$(USEMODULE))) + USEMODULE += usb_board_reset + + include $(RIOTMAKE)/tools/usb_board_reset.mk +endif diff --git a/cpu/esp32/usb_reset.c b/cpu/esp32/usb_reset.c new file mode 100644 index 0000000000..f3647f6edf --- /dev/null +++ b/cpu/esp32/usb_reset.c @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2023 Benjamin Valentin + * + * This file is subject to the terms and conditions of the GNU Lesser General + * Public License v2.1. See the file LICENSE in the top level directory for more + * details. + */ + +/** + * @ingroup cpu_esp32 + * @{ + * + * @file + * @brief Trigger reset to the bootloader stored in the internal boot ROM + * memory. + * + * This will start the USB/UART bootloader. + * + * @author Benjamin Valentin + * @author Gunar Schorcht + * + * @} + */ + +#include "driver/periph_ctrl.h" +#include "rom/usb/chip_usb_dw_wrapper.h" +#include "rom/usb/usb_persist.h" +#include "soc/rtc_cntl_reg.h" +#include "soc/rtc_cntl_struct.h" +#include "soc/soc_caps.h" +#if SOC_USB_SERIAL_JTAG_SUPPORTED +#include "soc/usb_serial_jtag_reg.h" +#include "soc/usb_serial_jtag_struct.h" +#endif + +#include "periph/pm.h" + +static void _reconfigure_usb(void) +{ +#ifdef CPU_FAM_ESP32S3 + /* disable USB OTG controller */ + periph_module_reset(PERIPH_USB_MODULE); + periph_module_disable(PERIPH_USB_MODULE); + + /* allow USB Serial/JTAG to use the internal USB transceiver */ + RTCCNTL.usb_conf.sw_usb_phy_sel = 0; + /* control the internal USB transceiver selection via hardware (efuse) */ + RTCCNTL.usb_conf.sw_hw_usb_phy_sel = 0; + /* don't enable USB transceiver function */ + RTCCNTL.usb_conf.usb_pad_enable = 0; + + /* select internal PHY for USB Serial/JTAG */ + USB_SERIAL_JTAG.conf0.phy_sel = 0; + /* enable USB pad function */ + USB_SERIAL_JTAG.conf0.usb_pad_enable = 1; +#endif +} + +void __attribute__((weak)) usb_board_reset_in_bootloader(void) +{ + /* If we are here, the USB port is not connected to the Serial/JTAG interface. + We have to re-configure it back to this mode first. */ + _reconfigure_usb(); + + chip_usb_set_persist_flags(USBDC_PERSIST_ENA); + REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT); + pm_reboot(); +}