Closed rikaiot closed 10 months ago
Also running into this. I wonder if there's a bit in a register somewhere we could flip before calling esp_restart
that would allow the USB-JTAG device to come back up. Or perhaps adding something like periph_module_disable(usb_otg_periph_signal.module);
before rebooting. I'll report back if we're able to figure out a workaround to this.
Things i've tried (that haven't worked):
periph_module_disable(usb_otg_periph_signal.module);
before rebootusb_del_phy
before reboot.I made a minimal repro case to demonstrate the issue: https://github.com/johnboiles/esp32-tinyusb-reset-bug
The only workaround we've found is to hook up a GPIO to the RESET pin and force the chip to reset itself. But it seems like there's probably just some register somewhere that needs to get reset at shutdown time.
I've been doing my testing on IDF 5.1 (cbce221e88).
The problem seems to be where in usb_new_phy
since if you remove that line the USB/JTAG doesn't go away https://github.com/espressif/idf-extra-components/blob/master/usb/esp_tinyusb/tinyusb.c#L58
I think I got it! TL;DR is something like this:
#include <esp_private/usb_phy.h>
extern usb_phy_handle_t *phy_hdl_ptr;
usb_del_phy(*phy_hdl_ptr);
usb_phy_config_t phy_conf = {
.controller = USB_PHY_CTRL_SERIAL_JTAG,
};
usb_phy_handle_t jtag_phy;
usb_new_phy(&phy_conf, &jtag_phy);
Where phy_hdl_ptr
is a global from TinyUSB by adding this line to tinyusb.c
(since you can't extern the static usb_phy_handle_t phy_hdl;
from tinyusb.c
)
usb_phy_handle_t *phy_hdl_ptr = &phy_hdl;
So now the question is how to we productionize this. Probably if there were a tinyusb_driver_uninstall
in tinyusb.c
that would be enough.
PR to propose tinyusb_driver_uninstall
: https://github.com/espressif/idf-extra-components/pull/229
@rikaiot thank you for reporting and @johnboiles thank you for your thorough investigation!
I'll review your changes ASAP. I need to discuss with colleagues whether we want to change (fix) the behaviout of esp_restart()
, too
Hello @johnboiles here is some update:
The restart behavior you see is actually intentional. If a user wants to perform a software reset, he usually does not want to re-enumerate as different device (JTAG debug) during the process.
Moreover, changing this would be a functional breaking change, so we will fix this with the changes you proposed in esp_tinyusb
component.
Even more info:
Makes sense to me that it's not the typical case to re-enumerate the USB/JTAG device after configuring TinyUSB.
Is there anywhere in the documentation that mentions which peripherals maintain their state across calls to esp_restart()
?
Is there anywhere in the documentation that mentions which peripherals maintain their state across calls to esp_restart()?
All of them, except Wi-Fi, BT, UART0, SPI1, and legacy timers
EDIT: Documentation is actually not entirely correct, as on ESP32-S2 and newer chips, if memory protection was enabled (and it was enabled by default) we did reset all the digital peripherals. This was fixed by https://github.com/espressif/esp-idf/commit/65bc1ed05530f1de49006f194966ec21007b17e8
esp_tinyusb v1.4.1 relased https://components.espressif.com/components/espressif/esp_tinyusb
Answers checklist.
IDF version.
v4.4.2
Operating System used.
Windows
How did you build your project?
Command line with idf.py
If you are using Windows, please specify command line type.
CMD
Development Kit.
ESP32-S3-DevKitM-1
Power Supply used.
USB
What is the expected behavior?
USB-JTAG is enabled by default, so when connecting the device via USB-Plug (not UART) to the PC the board is recognized as a JTAG-Interface in the device manager.
As soon as using TinyUSB CDC driver in the application by calling tinyusb_driver_install() and tusb_cdc_acm_init() the USB-JTAG is disabled and the device is recognized as a serial device.
When pressing the reset button or calling esp_reset() the board should again be recognized as USB-JTAG until the TinyUSB driver is loaded in the application.
What is the actual behavior?
When the TinyUSB has been loaded once, calling esp_reset() or forcing a watchdog reset does not make the device to be recognized as USB-JTAG any more.
Only when the reset button is pressed, the device is recognized as USB-JTAG again.
Steps to reproduce.
Connect the ESP32-S3-DevKitM-1 dev board to the pc via USB-Plug (not UART) - the device is recognized as USB-JTAG.
Initialize TinyUSB in the application by calling tinyusb_driver_install() and tusb_cdc_acm_init() after some delay.
The board is recognized as serial device.
Call esp_restart() or force and watchdog reset.
The board is not recognized as USB-JTAG again.
Press reset button - the board is recognized as USB-JTAG again until the TinyUSB initialization is done.
Debug Logs.
No response
More Information.
It seems that the USB-JTAG is disabled by TinyUSB and is not reactivated again when calling esp_restart().