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 can not exit from USB Serial/JTAG bootloader (IDFGH-12237) #13287

Open
3 tasks done
xyzzy42 opened this issue Feb 29, 2024 · 6 comments
Open
3 tasks done

ESP32-S3 can not exit from USB Serial/JTAG bootloader (IDFGH-12237) #13287

xyzzy42 opened this issue Feb 29, 2024 · 6 comments
Labels
Status: Opened Issue is new Type: Bug bugs in IDF

Comments

@xyzzy42
Copy link

xyzzy42 commented Feb 29, 2024

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.

v5.3-dev-0-g8171b22c40

Espressif SoC revision.

ESP32-S3 version 0.2

Operating System used.

Linux

How did you build your project?

Command line with idf.py

If you are using Windows, please specify command line type.

None

Development Kit.

Custom Board

Power Supply used.

Battery

What is the expected behavior?

Reset from Bootloader DOWNLOAD(USB/UART0) mode into normal SPI boot mode.

What is the actual behavior?

Reset always returns to DOWNLOAD(USB/UART0) mode.

Steps to reproduce.

  1. Pull GPIO0 and pulse CHIP_PU pin to enter bootloader.
  2. Use esptool.py to use RTS/DTR sequence on Espressif USB JTAG/serial debug unit to reset.

Alternatively, replace step 1 with software triggered bootloader reset:

REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
esp_restart();

Debug Logs.

ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0xc (RTC_SW_CPU_RST),boot:0x21 (DOWNLOAD(USB/UART0))
Saved PC:0x4038367a
waiting for download
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x15 (USB_UART_CHIP_RESET),boot:0x21 (DOWNLOAD(USB/UART0))
Saved PC:0x40041a76
waiting for download

First reboot is triggered via software using REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);esp_restart();. Second reboot is triggered via esptool. GPIO0 is not held low. But boot flags still do not have 0x08 bit set.

More Information.

If a device has no external reset button and permanently attached battery, it is impossible to exit bootloader!

@xyzzy42 xyzzy42 added the Type: Bug bugs in IDF label Feb 29, 2024
@espressif-bot espressif-bot added the Status: Opened Issue is new label Feb 29, 2024
@github-actions github-actions bot changed the title ESP32-S3 can not exit from USB Serial/JTAG bootloader ESP32-S3 can not exit from USB Serial/JTAG bootloader (IDFGH-12237) Feb 29, 2024
@igrr
Copy link
Member

igrr commented Mar 1, 2024

As you found, the hardware behavior is that the boot mode set by the strapping pins can't be overridden by USB_SERIAL_JTAG. This is because the strapping pins are only latched on power-on reset, RTC WDT reset, as well as brownout/SWD reset (i think). They are not latched again on the reset triggered by the USB_SERIAL_JTAG.

It's probably not something that ESP-IDF project can do anything about, as the reset behavior is determined at the hardware level.

However, I am not sure I understand the exact usage scenario:

  • First, you use GPIO0 and CHIP_PU to set the boot mode
  • But then, you flash using USB_SERIAL_JTAG.

If you have already used GPIO0 and CHIP_PU, it seems like you have a connection to those pins in the factory. Can you toggle CHIP_PU again after flashing is done? Seems like that is the simplest solution.

Alternatively, don't use CHIP_PU and GPIO0 to enter the download mode in the first place, and use USB_SERIAL_JTAG instead. In this case, it should be possible to get back to the flash boot mode once flashing is complete.

@xyzzy42
Copy link
Author

xyzzy42 commented Mar 1, 2024

This behavior is also observed when entering bootloader via software control, with:

    REG_WRITE(RTC_CNTL_OPTION1_REG, RTC_CNTL_FORCE_DOWNLOAD_BOOT);
    esp_restart();

In this case bootloader is entered without access to CHIP_PU and GPIO0.

It is also possible to enter bootloader by holding GPIO0 low and applying power to a dead battery. But once the battery is charged, there is no way to exit the bootloader other than to wait for the battery to fully discharge again. This make take hours or days!

We have built a sealed, wearable, device with no access to CHIP_PU nor ability to disconnect the battery. But we are also still doing software development, and might need to use the bootloader to flash new code. While the bootloader can be entered to reflash the software, it is not possible to exit the bootloader.

Documentation states that it is possible for JTAG/Serial device to reset into normal boot. ESP32-S3 Technical Reference Manual, §33.3.2:

Aside from general-purpose communication, the CDC-ACM interface also can be used to reset the ESP32-S3 and optionally make it go into download mode in order to flash new firmware.
Note that if the download mode flag is set when the ESP32-S3 is reset, the ESP32-S3 will reboot into download mode. When this flag is cleared and the chip is reset, the ESP32-S3 will boot from flash.

I have also observed that if the ESP32-S3 ROM bootloader is configured to use USB-OTG instead of USB Serial/JTAG, then it can exit bootloader when a reset is trigger via the USB-OTG CDC interface.

@Jason2866
Copy link

@xyzzy42
Copy link
Author

xyzzy42 commented Mar 1, 2024

It seems that only applies to entering bootloader via software. If it is entered via GPIO0 then there still is no way to exit without discharging the battery.

I did test that, but like the comments seem to indicate, it does not enter the bootloader. It reboots from user code into user code. I don't see how it's related to exiting the bootloader once the bootloader is entered.

That code is also interesting in other ways:

	// Maybe we need to consider tweaking these?
	chip_usb_set_persist_flags( 0 );  //NOT USBDC_PERSIST_ENA (1<<31)

	// We **must** unset this, otherwise we'll end up back in the bootloader.
	REG_WRITE(RTC_CNTL_OPTION1_REG, 0);
	void software_reset( uint32_t x );

But then if we look at ESP-IDF:

  * @brief Software Reset digital core.
  *
  * It is not recommended to use this function in esp-idf, use
  * esp_restart() instead.
  *
  * @param  None
  *
  * @return None
  */
void software_reset(void);

So should we use software_reset or not use software_reset? And does software_reset() have undocumented uint32_t argument? Because code in esp32 forum thinks it has one, but ESP-IDF header does not have one.

@xyzzy42
Copy link
Author

xyzzy42 commented Mar 5, 2024

I have also observed that if the ESP32-S3 ROM bootloader is configured to use USB-OTG instead of USB Serial/JTAG, then it can exit bootloader when a reset is trigger via the USB-OTG CDC interface.

It turns out this isn't exactly correct. If the bootloader is entered via software setting RTC_CNTL_FORCE_DOWNLOAD_BOOT, and the bootloader uses USB-OTG mode, then it's possible to exit the bootloader via RTS/DTR on the USB-OTG device. But if the bootloader is entered via GPIO0 pull-down on reset, then RTS/DTR will not exit the bootloader, for both USB-OTG or USB-JTAG (selected via eFuse USB_PHY_SEL).

This is contrary to what esptool code does and what @radimkarnis said in espressif/esptool#757 (comment). Perhaps that statement, from 2022, was correct for ESP32-C3 but is no longer correct for ESP32-S3?

So the bugs here are:

  • ESP32-S3 ROM bootloader: Implements RTS/DTR reset in a way that makes it impossible to exit bootloader.
  • ESP32-S3 Technical Reference Manual: Incorrectly claims RTS/DTR can exit bootloader into SPI flash boot mode and provides sequences to do so.
  • esptool for (at least) ESP32-S3: Only issues warning about bootloader exit impossible when bootloader uses USB-OTG mode, even though it is true for USB-Serial/JTAG mode as well.

@xyzzy42
Copy link
Author

xyzzy42 commented Mar 6, 2024

only latched on power-on reset, RTC WDT reset, as well as brownout/SWD reset (i think).

This gave me an idea, maybe the bootloader can be escaped by triggering a WDT reset. The TRM §8.1 agrees, "During power-on-reset, RTC watchdog reset, brownout reset, analog super watchdog reset, and crystal clock glitch detection reset …"

However, this also appears to not work as documented. An RTC WDT system reset did not restrap the pins:

ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x9 (RTCWDT_SYS_RST),boot:0x21 (DOWNLOAD(USB/UART0))
Saved PC:0x40378cae
waiting for download

Nor a RTC WDT RTC reset:

ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0x10 (RTCWDT_RTC_RST),boot:0x21 (DOWNLOAD(USB/UART0))
waiting for download

Nor does a Timer Group 0 WDT reset (wasn't in the list, but I tried anyway):

Build:Mar 27 2021
rst:0x7 (TG0WDT_SYS_RST),boot:0x21 (DOWNLOAD(USB/UART0))
Saved PC:0x40378cae
waiting for download

I can't see to figure out how to make the SWD trigger in the bootloader. I disabled the auto-feed and the SWD interrupt, but it still isn't triggering. If the SWD can trigger a chip reset and not just a system reset, then maybe it could do it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Opened Issue is new Type: Bug bugs in IDF
Projects
None yet
Development

No branches or pull requests

4 participants