ESP32 waking from deep sleep into Flash mode

I’ve got a strange issue whereby a small number of production devices (ESP32-Wrover with SPIRAM, running on a custom PCB via battery) will go to into deep sleep as expected, but when the timer wakes them up, they go straight into Firmware Update mode. GPIO0 is exposed to a usb-c port for manual flashing purposes, but not connected to any cables when this happens.

Is there a firmware / ESP-IDF setting that I’m missing somewhere to ensure that GPIO is held low when the device goes to sleep to prevent this from happening? It’s almost as though the internal pull-down is failing.

Alternatively, any other suggestions would be very welcome!

I don’t know the internals of the chip. Sometimes current sources are disabled to reduce power drain, and pull-ups/downs use to be power sources.
AFAIK GPIO0 = low is needed to enter flashing mode, so you should keep it high, not low. I would use a resistor.

Sorry my bad - I meant pull high! There’s an internal pull-up on the ESP32 so I’m not supposed to need an external resistor. It’s just strange that 99% of the time it’s fine, then will suddenly fail and because it’s on battery power, it just gets stuck.

I don’t suppose there’s any way in ESP-IDF to set a time-out on flash mode, so after X minutes it reboots again?

I’m too lazy to read the datasheet, I picked up random lines here and there at the IDF docs stating that the microcontroller is powered off exept for the RTC. I’ve also seen that GPIOs having to hold a state have to be explicitly set. I would bet that the pull-up is also deactivated, why don’t just solder a resistor on those units and check ?

I would also bet the flash code runs on a chip internal ROM (as most microcontrollers do), and the IDF can’t do anything about that.

It happened to me before as well - some chips have a very weak pull-up or maybe no pull up at all - it is better to pull it up explicitly with something like 100K resistor.

Ouch, thats got to hurt battery life. I’m looking at designing a battery based project so would be great to know more.

@arkhipenko can you give any advice on what types of devices you’ve seen problems like this?
@needlerp any chance you can tell us what unit/what supplier you used for this project thats experiencing the issues?

The datasheet states a typical pull-up resistor value of 45K @3.3V @25ºC, with no min and no max. I would use a resistor.

Thanks. We already have several hundred devices in the field, and are trying to avoid recalling them all to manually solder on an external pull-up! We’ve also found it impossible to replicate the issue once we get faulty units back (unless we manually hold GPIO0 low).

I’m using ESP32-Wroom. Is there a way to force GPIO in the right state with the internal pull-up using code before going to sleep, to try and avoid any ‘floating’ scenario for those devices already in the field?

The weak pull-up is a current source inside the ESP32 chip. Of course different modules might have different ESP32 variants, but those are in terms of number of cores and memory capabilities. AFAIK all ESP32 have the same GPIO0 structure.

If your problem is not reproducible in the lab, it may be due to environmental causes.
An unbounded 45K pull-up means that any residual humidity draining 50uA will put you in serious trouble. Yes. that is high, though.
A floating pin with a weak pull-up, no filtering, and perhaps being exposed for the sake of easy reprogramming may be susceptible to noise; though latch-ups are not so common these days (the internal pin structure might act like an SCR and short circuit to ground or Vdd).

I did not deeply dive into the internals, but as I said before, the chip is mostly powered off in deep-sleep. That means that when waking up, it will start up just like on reset. GPIO0 is a strapping pin; the datasheet states this:

During the chip’s system reset release (power-on-reset, RTC watchdog reset and brownout reset), the latches of
the strapping pins sample the voltage level as strapping bits of ”0” or ”1”, and hold these bits until the chip is
powered down or shut down. The strapping bits configure the device’s boot mode, the operating voltage of
VDD_SDIO and other initial system settings.
Each strapping pin is connected to its internal pull-up/pull-down during the chip reset. Consequently, if a
strapping pin is unconnected or the connected external circuit is high-impedance, the internal weak
pull-up/pull-down will determine the default input level of the strapping pins.
To change the strapping bit values, users can apply the external pull-down/pull-up resistances, or use the host
MCU’s GPIOs to control the voltage level of these pins when powering on the chip.
After reset release, the strapping pins work as normal-function pins.

That means that you can’t control the pull-up/pull-down internal resistors on reset.
Unless there is a difference on deep-sleep wake-up that I’ve overseen, you need hardware to solve your problem.

That’s really helpful, thank you!