Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESP32-S3: USB-JTAG not working after esp32_reset() or Watchdog-Reset when TinyUSB CDC was initialized in application once (IDFGH-8354) #9826

Closed
3 tasks done
rikaiot opened this issue Sep 21, 2022 · 9 comments
Assignees
Labels
Resolution: Done Issue is done internally Status: Done Issue is done internally Type: Bug bugs in IDF

Comments

@rikaiot
Copy link

rikaiot commented Sep 21, 2022

Answers checklist.

  • I have read the documentation ESP-IDF Programming Guide and the issue is not addressed there.
  • I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
  • I have searched the issue tracker for a similar issue and not found a similar issue.

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.

  1. Connect the ESP32-S3-DevKitM-1 dev board to the pc via USB-Plug (not UART) - the device is recognized as USB-JTAG.

  2. Initialize TinyUSB in the application by calling
    tinyusb_driver_install()
    and
    tusb_cdc_acm_init()
    after some delay.

  3. The board is recognized as serial device.

  4. Call esp_restart() or force and watchdog reset.

  5. The board is not recognized as USB-JTAG again.

  6. 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().

@rikaiot rikaiot added the Type: Bug bugs in IDF label Sep 21, 2022
@espressif-bot espressif-bot added the Status: Opened Issue is new label Sep 21, 2022
@github-actions github-actions bot changed the title ESP32-S3: USB-JTAG not working after esp32_reset() or Watchdog-Reset when TinyUSB CDC was initialized in application once ESP32-S3: USB-JTAG not working after esp32_reset() or Watchdog-Reset when TinyUSB CDC was initialized in application once (IDFGH-8354) Sep 21, 2022
@johnboiles
Copy link

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.

@johnboiles
Copy link

johnboiles commented Aug 25, 2023

Things i've tried (that haven't worked):

  • periph_module_disable(usb_otg_periph_signal.module); before reboot
  • Try to deep sleep for 5s (I was thinking maybe this would power cycle the USB peripheral)
  • usb_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 (cbce221).

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

@johnboiles
Copy link

johnboiles commented Aug 26, 2023

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.

@johnboiles
Copy link

PR to propose tinyusb_driver_uninstall: espressif/idf-extra-components#229

@tore-espressif
Copy link
Collaborator

tore-espressif commented Sep 1, 2023

@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

@tore-espressif tore-espressif self-assigned this Sep 1, 2023
@espressif-bot espressif-bot added Status: In Progress Work is in progress and removed Status: Opened Issue is new labels Sep 1, 2023
@tore-espressif
Copy link
Collaborator

tore-espressif commented Sep 5, 2023

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:

  • Software reset (esp_restart()) and WDT restart are not considered the same. The software reset is deemed as regular software flow, while WDT timeout is considered panic abort
  • You can read more about SW reset here and about WDT timeout here

@johnboiles
Copy link

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()?

@tore-espressif
Copy link
Collaborator

tore-espressif commented Sep 6, 2023

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

https://docs.espressif.com/projects/esp-idf/en/latest/esp32s3/api-reference/system/misc_system_api.html#_CPPv411esp_restartv

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 65bc1ed

@tore-espressif
Copy link
Collaborator

@espressif-bot espressif-bot added Status: Done Issue is done internally Resolution: Done Issue is done internally and removed Status: In Progress Work is in progress labels Sep 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Resolution: Done Issue is done internally Status: Done Issue is done internally Type: Bug bugs in IDF
Projects
None yet
Development

No branches or pull requests

4 participants