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

Firmware programming using native USB port on ESP32-S3 does not work #331

Open
dkalliv opened this issue Feb 10, 2023 · 16 comments
Open

Firmware programming using native USB port on ESP32-S3 does not work #331

dkalliv opened this issue Feb 10, 2023 · 16 comments

Comments

@dkalliv
Copy link

dkalliv commented Feb 10, 2023

I tried to upload my firmware using the native USB port of some ESP32-S3 based devices (Epressif ESP32-S3-DevKitC-1, WT32-SC01 Plus as well as one of my own designs). Unfortunatelly the upload (programming) fails with the message "Installation failed, The device has been lost."
esp-web-tools
It looks like the programming works fine, but towards the end the transfer speeds up like crazy and then fails...

However programming works just just fine, when using an USB to UART bridge (same firmware, same manifest). Interestingly I can program the devices with esptool-js using the native USB port without any issues (using the same firmware).
esptool-js

Just to be sure that this is not related to my system, I've tried the same thing on three different Windows 10 systems and on one system running Windows 11 (not sure if the problem is present on Apple systems as well). I've experienced the same behavior on Microsoft Edge as well as on Google Chrome.

Do you have any idea how this could be fixed?

@balloob
Copy link
Member

balloob commented Feb 11, 2023

Has been fixed upstream but has not been released yet. We'll update when available.

@dkalliv
Copy link
Author

dkalliv commented Mar 5, 2023

Hi Paulus,
unfortunately the problem persists after the fix in esptool-js. This kept bugging me, so I invested a few hours yesterday to do some extensive testing. I found the following behavior, which might help you identify the root cause:

  • When programming an ESP32-S3 using an USB to UART bridge it always works (using esptool.js, esp-web-tools, PlatformIO or the Arduino IDE).
  • When using the native USB port, programming works using esptool.js, PlatformIO or the Arduino IDE. For esp-web-tools it works only (once) if the device was previously erased or was programmed with a really small firmware (something like a simple "Hello World").
  • As soon as a “larger” firmware (around 1.3 Mbytes in my case) has been written to a ESP32-S3 device, using native USB and esp-web-tools, any subsequent attempt to write a larger firmware to the device will cause it to fail with a "the device has been lost" error message.
  • From this point on, the device seems to be corrupted in such a way, that no larger firmware can be programmed over native USB (also not using PlatformIO or the Arduino IDE or even Espressif's Flash dowload tool).
  • The device can be "healed" by uploading a small firmware (either over native USB or an USB to UART bridge) using esptool.js, esp-web-tools, PlatformIO or the Arduino IDE.
  • Any attempt to erase the device, after an upload of a larger firmware has been aborted with the "the device has been lost" error message, will further "corrupt" the device by causing a boot loop.
  • Unfortunately I can not simply automatically erase the device before every upload (the obvious workaround), as attempting to erase a device containing a larger firmware with esp-web-tools (even after a successful upload of a larger firmware) will corrupt the device with a boot loop. Erasing the device with esptools.js however will not corrupt the device.
  • No device corruption occurs (irrespective of the firmware size) using esptool.js to program or erase the device.

Feel free to reach out to me, if you need more information or further testing...

@balloob
Copy link
Member

balloob commented Mar 6, 2023

Weird.

When we erase the flash, we call erase_flash()

await esploader.erase_flash();

Esptool-js supports flashing on write too, but that calls the same logic:

https://github.com/espressif/esptool-js/blob/e8d66b62bfec8c416e65fca614e06965b8bf78fa/src/esploader.ts#L900

@Jason2866
Copy link
Contributor

Could be the old stub loader code used in esptool.js. There where some mandatory bug fixes for the S3 in native USB mode in esptool.py stub loaders.

@dkalliv
Copy link
Author

dkalliv commented Mar 8, 2023

Yes, there where quite a few fixes in the stub, but actually I tried the stub from esptool.py 4.5.1 and experience the same behavior. The only difference being, that the upload failed a bit earlier (at around 30% instead of at around 80%). I assume (kind of thinking loud) that this has to be kind of a timeout/watchdog issue in the stub that is not triggered by smaller firmware as the upload process is shorter.
But this does not explain, why things work using plain esptool.js. I even "hacked" together a firmware upload facility using esptool.js (with the old stubs) and everything works as expected. So I agree with Paulus: this is weird...

One difference I was able to spot is how flash size, frequency, etc are handled, when calling write_flash()

esp-web-tools/src/flash.ts

Lines 184 to 190 in 0e0bc1d

await esploader.write_flash(
fileArray,
"keep",
"keep",
"keep",
false,
true,

vs
https://github.com/espressif/esptool-js/blob/e8d66b62bfec8c416e65fca614e06965b8bf78fa/index.js#L292-L298
not sure if this could be related..?

@Jason2866
Copy link
Contributor

Have you tried when changing this values?

@dkalliv
Copy link
Author

dkalliv commented Mar 11, 2023

Yes, I've tried changing these values, but as expected, it did not make any difference. I would have been surprised, if this was the cause, since flashing over an USB to UART bridge works, using exactly the same call...

Can anybody replicate the problem or am I the only one facing this issue?

@sblantipodi
Copy link
Contributor

I have the same issue when I try to configure the WiFi via the ESP Web Tools interface.
It says disconnected, but wifi is successfully configured after that error message.

@SuGlider
Copy link

The S3 native USB has 3 modes: (1) CDC/JTAG || (2) OTG - TinyUSB driver || (3) disabled
Each of these 3 modes are activated by the running firmware of the S3, right after booting.

USB Web tools and other uploading modes work best with the (1) CDC/JTAG.
It is possible to activate this mode by uploading an empty (or small) firmware/sketch that sets the CDC/JTAG mode.
But if the next uploaded firmware is created/programmed to use (2) or (3), the following uploads using USB will fail.

Therefore, S3 demands that CDC/JTAG is activated by the running firmware and that all next firmwares keep this mode always active.

@TD-er
Copy link

TD-er commented May 28, 2023

@SuGlider
That's also what I noticed.
But as a side-question, how to do this with the ESP32-S2?
As far as I know, it doesn't support HWCDC. (and if it does, I would really like to know about it)

@Jason2866
Copy link
Contributor

To workaround this S3 bug esptool.py and esptool.js needs to be enhanced to do this (set up S3 to work correctly with cdc/jtag) without any user interaction.

@SuGlider
Copy link

To workaround this S3 bug esptool.py and esptool.js needs to be enhanced to do this (set up S3 to work correctly with cdc/jtag) without any user interaction.

This is not a esptool.py bug, because it works fine with ESPTOOL.py. This is a limitation of WEB-USB-tools.

The work around for S3/S2 USB is to set USB DFU mode manually (ROM) by keeping BOOT pressed and pulsing RESET/EN.
It needs user interaction... It seems to fail with WEB-Tools.

https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-guides/dfu.html

@SuGlider
Copy link

Check this video: https://www.youtube.com/watch?v=Zqqj8GC0Q9Q
BOOT + RESET activates S2 TinyUSB ROM layer and then the computer is able to enumerate it.

@TD-er
Copy link

TD-er commented May 28, 2023

Can the web flasher toggle the CTS/RTS pins?
In the USBCDC code, there is some code to detect this and issue a reboot.

@dkalliv
Copy link
Author

dkalliv commented Jun 1, 2023

As I do use CDC/JTAG for the USB mode on my S3 devices, this can not be the issue. By now I am suspecting, that the issue is somehow related to Windows not playing nicely with something in esp-web-tools: A few weeks ago, I switched my main workstation to Linux and noticed, that the issue went away (uploading using Chromium). When going back to Windows the problem reappears and the device gets corrupted, after the upload process aborts with the "The device has been lost" message.
Uploading a tiny firmware (also configured to use CDC/JTAG) makes the device programmable again.
I've build my own "web-upload-facility" based on esptool-js and this works on Windows and Linux with the exactly same firmware files that cause the issue when attempting an upload with esp-web-tools. I would rather use esp-web-tools, which is very pretty and refined, instead of investing the time to make my own solution look good...

A side note: I do not use a merged firmware file, I use a manifest with four parts.

@TD-er
Copy link

TD-er commented Jun 1, 2023

@dkalliv See also my comment here: espressif/esptool-js#97 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants