The missing part of Espressif’s reset circuit

In the previous article, we peeked at the reset circuit of ESP-Prog with an oscilloscope, and reproduced it with basic components. We observed that it did not behave quite as expected. In this article, we’ll look into the missing pieces.

The expected behavior of the reset circuit.
What we actually observe, in either the ESP-Prog itself, or in the reproduced circuit.

An incomplete circuit

For a hint, we’ll first look a bit more closely at the schematics of the ESP-Prog. Of course, we find the automatic reset circuit itself:

But, right next to it, we find another circuit that can set the electrical level of ESP_EN and ESP_IO0_B:

We can find the physical location of these components in the PDF that describes the PCB layout. Conveniently, you can just hit Ctrl+F and search for SW1/SW2/R7/R8/C16/C19. All of them are situated next to the USB micro-B port:

As indicated by the labels next to the buttons the blue boxes in the schematics SW1 and SW2 correspond to the RST and BOOT press buttons respectively.

We also see two resistors that connect ESP_EN and ESP_IO0_B to the 3.3V rail “VDD3V3”. These are pull-up resistors: when the button is not pressed, they “pull” the electrical level to 3.3V; when the button is pressed, the direct (0Ω) connection to ground “takes priority” over the 10kΩ connection to the 3.3V rail, so the electrical level drops to 0V. In other words, they make it so that the two signals “default” to 3.3V.

There are also two small-value capacitors next to the switches. These are here to debounce button presses. That is, the button momentarily causing multiple contacts due to physical “bouncing”.

However, these components are not actually present in the board. The “(NC)” suffix stands for “Not Connected” and is reaffirmed by the green font. We can verify this visually: if we look closely at each of the locations where R7, R8, C16 and C19 should be, we can see two pads with solder, but no component in between.

These components are not present by default in the board. But users may choose to add them by soldering them manually. This is actually a good hint at what is going on: in some circumstances, we might or might not want to have these components present. And this depends… on the connected board!

The missing pieces

To understand this, we need to look at the schematics of the target board as well. In my case, I will be using ESP32-S2-Saola-1RI. The ESP-Progs’s EN and IO0 pins connect to the Saola’s CHIP_PU (for Power-Up) and GPIO0 pins. We find various circuits connected to these:

The two circuits depicted above are the RST and BOOT buttons of the Saola board. Just like those of the ESP-Prog board, they have an optional capacitor (although of different suggested value) to debounce presses. As long as the button is not pressed, this should not impact the electrical level of CHIP_PU or GPIO0.

Again, the circuit above look very similar to one in the ESP-Prog. This is due to the Saola board having its own UART-to-USB adapter (a CP2102N chip). R28 and R29 are “0Ω resistors”, which means that they act as wires, but can be easily desoldered to disable the automatic reset circuit entirely. As long as we do not use the Saola’s USB port, DTR and RTS should stay floating and not affect CHIP_PU or GPIO01.

This is starting to get interesting. We find a 10kΩ resistor R36 that pulls CHIP_PU up to 3.3V and a 1µF capacitor C22 between CHIP_PU and the ground. This time, they are not marked “(NC)”. The schematics of the Saola are slightly less convenient, but we can still locate their physical location by searching the PDF.

Since it can be hard to tell, I have added labels showing the location of R36 and C22.

From this, we can find them on the board:

Incidentally, notice the two components with the upside-down “J3Y” markings are the transistors from the Saola’s automatic reset circuit, just like in the ESP-Prog. Also, the square chip that takes most of the bottom left quadrant of the picture is the CP2102 USB-to-UART adapter.

This resistor and this capacitor are real! They are not just a figment of our imagination!

There is one final component to find, but we won’t find it in the schematics of the Saola board. We’ll have to take a look at the datasheet of the ESP32-S2 microcontroller itself!

Page 17 (2.4. Strapping Pins)
Page 38 (4.4. DC Characteristics Table 12)

From this, we can deduce that, inside the ESP32-S2 microcontroller, there is a 45kΩ pull-up resistor connected to GPIO0.

Note: I actually assumed a 10kΩ before finding Table 12 and the information below still uses that. However, it should not change anything to the main discussion.

Adding resistors

First, let add the resistors R36 and RPU to the SPICE simulation we used in the previous article.

This is the result:

This is promising! Although there are a few artifacts (which could just be inaccuracies of the simulation), EN and IO0 are behaving as we expect!

We can also add these resistors to the breadboard circuit:

The two pull-up resistors are on the left. The red wire brings the 3.3V electrical level from the UART-to-USB adapter.

When I run the same C program as before and observe the behavior on an oscilloscope, this is what I observe:

This is exactly the behavior we expected from the logical gate! We are done!

But… are we?

Connecting a board

Let’s connect the ESP-Prog to the Saola board, and see how it behaves in a realistic situation.

ESP-Prog connected to Saola board

This is still slightly different from what we expect. For a quick sanity check, let’s see how the basic breadboard circuit (without the pull-ups) behaves if we connect it to the Saola board.

Breadboard circuit without pull-ups, connected to Saola board

This is virtually identical. We can zoom in on EN and IO0 to confirm:

ESP-Prog connected to Saola board, EN and IO0 only
Breadboard circuit without pull-ups, connected to Saola board, EN and IO0 only

What we are seeing is the capacitor slightly delaying the rise of EN, relative to the rise of IO0 to avoid any ambiguity.

If we wanted to restart the board into bootloader mode, we would first toggle RTS (bringing it low), causing EN to also become electrically low, and turning the microcontroller off. We would then flip both DTR and RTS, bringing them electrically low and high, respectively; this would result in:

  • EN becoming electrically high, thus starting the microcontroller
  • IO0 becoming electrically low, which the microcontroller would interpret as a choice to start in bootloader mode

However, without the capacitor, the microcontroller could measure IO0 before it actually rose to 3.3V thus failing to select bootloader mode. With it, IO0 will rise to 3.3V even before EN could start the chip. You can see this in the screenshot below.

When we toggle both DTR and RTS, IO0 immediately becomes electrically low, but EN is slightly delayed.

This is actually documented in page 18 of the ESP32-S2 datasheet:

The minimum value given for tSU is 0 ms, but that does not mean that things will work without the capacitor. Multiple people had issues related to a missing delay: [1], [2], [3]. See also another investigation of the reset circuit here.

So, let’s add C22, the capacitor we found in the Saola’s schematics!

Adding a capacitor

First, in the SPICE simulation:

On EN, we see something very close to what we expect, with a slow rise, instead of a sharp edge.

The added 1µF capacitor in the upper right connects EN to the ground, which is brought by the black wire from the UART-to-USB adapter.

We can again measure the breadboard circuit on its own (no Saola board connected to it):

Breadboard circuit with pull-ups resistor and delay capacitor, no board connected

EN now behaves almost exactly as the ESP-Prog connected to the Saola board. The slight difference in the shape of the rising slop on EN will be discussed in the next article. As far as I can tell, the slight voltage drops on IO0 are due to the behavior of the ESP32-S2 chip itself when it is powered down.

Breadboard circuit with pull-ups resistor and delay capacitor, no board connected, EN and IO0 only
ESP-Prog connected to Saola board, EN and IO0 only

Wrapping up

From these experiments, we have gained a pretty solid grasp of the circuit used for automatically resetting the microcontroller into bootloader mode in Espressif boards. You can play with the simulation below to see it in action. The most interesting sequence of action is the one used to trigger the reset into bootloader mode:

  1. Toggle the switch next to RTS to make it electrically low.
  2. Pause the simulation by clicking on the “RUN / Stop” button in the upper right.
  3. Toggle the switch next to DTR to make it electrically low.
  4. Toggle the switch next to RTS to make it electrically high.
  5. Resume the simulation by clicking on the “RUN / Stop” button in the upper right.
  6. Wait and observe the electrical levels of EN and IO0.
  1. I am actually unsure this is true. But this is a good enough approximation here. ↩︎

One thought on “The missing part of Espressif’s reset circuit

Leave a Reply

Your email address will not be published. Required fields are marked *