2

I have an ESP32 board with GPIO0 connected to ground through a switch. The idea is that if I press the button and issue an ESP.restart() the board would get into flash mode. Instead, ESP.restart() just restarts the app, ignoring GPIO0 state.

Is it possible to force the whole boot process, maybe with a direct JMP to the HW reset vector?

Paperino
  • 935
  • 7
  • 14
  • what is the state of GPIO2? This is also required to be disconnected or pulled low to enter ROM boot mode. – theCreator Apr 30 '21 at 01:42
  • did you try ESP.reset()? – Juraj Apr 30 '21 at 11:56
  • GPIO2 is left unconnected as per ESP32 Boot mode selection instructions https://github.com/espressif/esptool/wiki/ESP32-Boot-Mode-Selection And yes, did try ESP reset which didn't make a difference. If I physically power cycle the MCU will do a full boot and as such won't ignore GPIO0. I haven't tried grounding EN yet, but I expect to work. So there must be a jump vector somewhere that does it properly – Paperino Apr 30 '21 at 22:23
  • sorry esp32 doesn't have ESP.reset(). only esp8266 has it. – Juraj May 01 '21 at 16:55
  • Some futile attempts: 1. tried to wipe the OTA_DATA partition, but apparently the bootloader picks the first one and reconstructs it? 2. tried to wipe the whole partition table, but ```spi_erase_range``` is set to abort() as default for the Arduino library. It seems like a custom bootloader, which doesn't boot if the OTA_DATA partition is blank or some similar mechanism is the way to go. – Paperino May 04 '21 at 15:11
  • This seems relevant: The bootloader has the CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP option which allows to reduce the wake-up time (useful to reduce consumption). This option is available when the CONFIG_SECURE_BOOT option is disabled. Reduction of time is achieved due to the lack of image verification. During the first boot, the bootloader stores the address of the application being launched in the RTC FAST memory. And during the awakening, this address is used for booting without any checks, thus fast loading is achieved. I will try to wipe RTC memory as well. – Paperino May 04 '21 at 15:21
  • Follow up: ESP.Restart() does wipe the RTC memory. – Paperino May 04 '21 at 16:18

2 Answers2

2

According to Ivan Grokhotkov

On ESP32 there are 3 reset reasons which cause strapping GPIOs to be sampled: power-on, RTC WDT reset, brownout reset.

So in terms of code, see below. If the pin is strapped it will never get out of the bootloader which will be waiting for a sync on serial.

#include "soc/rtc_wdt.h"
void hardReset() {  
  rtc_wdt_protect_off();      //Disable RTC WDT write protection
  //Set stage 0 to trigger a system reset after 1000ms
  rtc_wdt_set_length_of_reset_signal(RTC_WDT_SYS_RESET_SIG, RTC_WDT_LENGTH_3_2us);
  rtc_wdt_set_stage(RTC_WDT_STAGE0, RTC_WDT_STAGE_ACTION_RESET_SYSTEM);
  rtc_wdt_set_time(RTC_WDT_STAGE0, 10000);
  rtc_wdt_enable();           //Start the RTC WDT timer
  rtc_wdt_protect_on();       //Enable RTC WDT write protection
}
Paperino
  • 935
  • 7
  • 14
  • how is this the answer? – Juraj May 12 '21 at 14:21
  • ESP.restart() just restarts the app, ignoring GPIO0 state. The solution above while restart the board and allows the use of the GPIO0 pin to decide if the bootloader should launch the app or not. – Paperino May 12 '21 at 21:24
  • so the answer is hardware watchdog reset and this is how to do it – Juraj May 13 '21 at 05:39
0

A better solution is that not using firmware update mode for programmatically software updates, use it only for only bootloader updates. Split your code into two-part bootloader and logical program part.

To update your logical program part, your bootloader should handle burning the remaining addresses except for the bootloader. (Your bootloader code can burn any address on the microcontroller, filesystem libraries do that) So don't try to switch into firmware update mode which is available for whole firmware updates. The more advanced solution is using OTA update features as possible as.

In this way, you guarantee that you always have the bootable device in the field, which is ready to update any corrupted logical part. Any mistake during burning the bootloader in the field may cost your device shipment.

raxetul
  • 439
  • 5
  • 12
  • Ideally, I totally agree. My FW does indeed support OTA update. The problem is that during development is possible to introduce bugs that break OTA functionality, so - of course I am talking about development and not deployment - it's important to have a way to flash the board via wires. The first rev of the board I worked on didn't have this simple safeguard and we had to throw away a few pieces before figuring out a sequence of code that must run at every boot. And every so often that would be accidentally broken too. – Paperino May 12 '21 at 21:28