Hello Forum Folks,
There have been numerous conversations about the behavior of the clever little 2-Transistor circuit used on DevKit boards to allow for Host tools to initiate bootloader and code download to ESP devices. Seemingly inexplicably it works "no problem" for some people, "never" for some, and "Sometimes" for the rest of us. We recently dug a bit deeper to see if we could understand the problem and to propose a fix which would not have other undesirable system consequences.
The typical go-to solution has been to hang a capacitor on the EN signal. This has the effect of slowing its rise time, and (hopefully) catching IO_0 as being LO at the time the ESP wakes up. There are numerous problems with this approach and it can lead to other forms of system unreliability. Furthermore, it still actually doesn't always work.
The real problem here is in the Host OS software. The transistor circuit was designed with the intention that the controlling signals transition simultaneously. In practice, these signals do not transition simultaneously because each transition is triggered by a distinct command. The time between execution of each of these commands is actually dependent on the Host OS and driver implementation.
In our development setup, we experienced an EVEN LONGER delay between these transitions as we have an ESP development environment embedded in a VM which runs on a host. Because of USB virtualization, each command has to traverse two (or three) OS-uncertainty domains before it is executed. The delays, and delay variations, we observed were diverse and quite long.
Hanging an arbitrarily large capacitor off of the EN signal was not a good option, nor scalable.
After some sleuthing to understand this issue, a bit of circuit analysis, and a bit of spice simulation, we have arrived at a solution we would like to present to the community. The "short" version is that a capacitor connected to the BASE of Q1 in the DevKit schematic has the effect of delaying the transition of EN without significantly affecting its rise time. In other words, the circuit operates as designed, despite significant delay between the control signal transitions. We were able to mask 20+ ms delays with this method, which was sufficient to bridge the delays we observed.
The "long" version is contained in the attached document:
Here we describe the problem and the proposed solution, including scope traces, simulations, and a circuit analysis.
We hope that the community finds this information useful, and that this fix might one day be considered for integration into the DevKit schematics as a way to better mitigate this problem for future users. As can be seen in the document, implementing the fix on current DevKit boards is pretty straightforward as an aftermarket mod. Not much different than the capacitor on EN in complexity.
Thanks for your consideration of this solution, and we look forward to your thoughts and comments. We hope that this helps the community have a more enjoyable and productive Espressif experience!
DevKit Auto USB Programming: A New Fix
-
- Posts: 9769
- Joined: Thu Nov 26, 2015 4:08 am
Re: DevKit Auto USB Programming: A New Fix
That is really extensive, thanks for that! I'll probably still advise people to add a cap between EN and GND as the first order see-if-that-fixes-things because EN is available outside of the devboard which makes trying that easily, but I'll surely also link to this post for a 'more better' solution. I'll also ping the hardware dev people in Espressif, let them take a look at this and see if they see any downsides incorporating this in future designs.
The only thing I don't like is that you're effectively discharging a fully-charged and large (33uF!) capacitor straight over the base-emitter junction of the transistor; the current is only limited by the fact that the RTS pin of the CP2102 can probably only sink so much current. Wouldn't it be more prudent to split R21 into two: e.g. DTR, then a 4K7 to the capacitor, then an 1K to the base of the resistor? Nice thing there is that the discharge curve isn't determined by whatever current RTS is limited to, but the time is mostly determined by the RC time of the 1K resistor and capacitor, which are known values. Additionally, it allows the capacitor not to be a big hunking 33uF, but a lot smaller.
I do kinda agree with the 'underbiased' comment, by the way: the circuit works for the S8050 transistors usually used, but I've seen people use different transistors and have it not work as the DC gain of those was a bit lower; the fix is to use lower-value resistors.
The only thing I don't like is that you're effectively discharging a fully-charged and large (33uF!) capacitor straight over the base-emitter junction of the transistor; the current is only limited by the fact that the RTS pin of the CP2102 can probably only sink so much current. Wouldn't it be more prudent to split R21 into two: e.g. DTR, then a 4K7 to the capacitor, then an 1K to the base of the resistor? Nice thing there is that the discharge curve isn't determined by whatever current RTS is limited to, but the time is mostly determined by the RC time of the 1K resistor and capacitor, which are known values. Additionally, it allows the capacitor not to be a big hunking 33uF, but a lot smaller.
I do kinda agree with the 'underbiased' comment, by the way: the circuit works for the S8050 transistors usually used, but I've seen people use different transistors and have it not work as the DC gain of those was a bit lower; the fix is to use lower-value resistors.
Re: DevKit Auto USB Programming: A New Fix
Amazing write-up!
I will be trying this method soon, since the existing ones have always been finicky. Especially with an Ethernet PHY in the mix.
I agree with ESP_Sprite on the shorting of a large capacitor. You should consider revising your doc to present the solution of adding another 1k resistor. I guess it isn't as easy to hack onto an existing dev board though...
I will be trying this method soon, since the existing ones have always been finicky. Especially with an Ethernet PHY in the mix.
I agree with ESP_Sprite on the shorting of a large capacitor. You should consider revising your doc to present the solution of adding another 1k resistor. I guess it isn't as easy to hack onto an existing dev board though...
Re: DevKit Auto USB Programming: A New Fix
Thanks for the comments. 100% agree that this is not a perfect solution, but was meant to be easily implemented.
Hopefully the Espressif folks will see the concept here, and actually fix the circuit for everyone. Really if you think about it, this solution is at least no worse than putting a cap on EN, which is really just a poor idea for so many reasons. Current is certainly limited by what RTS is willing to sync, and likely doesn't violate any parameters of the device itself (dissipation in the driver, etc...) as output drivers are expected to tolerate short duration short circuit conditions. The voltage the RTS output sees is also at least a diode-drop lower than the fully charged cap voltage. This is no justification, but simply reality. A small value R in series with the cap would indeed be a good addition to this, and probably allow for use of a smaller value cap.
Again, in contrast to significantly slowing the rise time of EN, even as implemented this solution is probably better for the overall system in terms of reliability and repeatability. For us, we needed a particularly large delay due to the embedded VMs. However, with any changes in OS the latency between transitions could be unpredictable. Further, the cap-on-EN solution depends heavily on external loading of the EN signal... so that solution may stop working in systems where there are a number of devices which share EN or the Host OS DTR-RTS inter-signal latency grows or is variable.
The purpose of this alternative is to also remove this EN signal loading dependency.
Lastly, one could make a similar short circuit complaint about placing a capacitor on EN. The signal which drives it low also has to deal with a short-circuit condition when discharging the cap. In this regard, perhaps the two solutions are not so dissimilar? Remember, EN can be driven by any external circuit, the ESP32 itself, or our little reset circuit. Since there are more places out of our control where this could go wrong (weak external driver) it can lead to more side effects, and in effect the same "short circuit" condition with an actually higher voltage (no extra diode drop).
Thanks for pointing out this additional facet which was not well called out in the write up. It's great to have more eyes looking at these things to find areas for further improvement and deeper explanation.
Hopefully the Espressif folks will see the concept here, and actually fix the circuit for everyone. Really if you think about it, this solution is at least no worse than putting a cap on EN, which is really just a poor idea for so many reasons. Current is certainly limited by what RTS is willing to sync, and likely doesn't violate any parameters of the device itself (dissipation in the driver, etc...) as output drivers are expected to tolerate short duration short circuit conditions. The voltage the RTS output sees is also at least a diode-drop lower than the fully charged cap voltage. This is no justification, but simply reality. A small value R in series with the cap would indeed be a good addition to this, and probably allow for use of a smaller value cap.
Again, in contrast to significantly slowing the rise time of EN, even as implemented this solution is probably better for the overall system in terms of reliability and repeatability. For us, we needed a particularly large delay due to the embedded VMs. However, with any changes in OS the latency between transitions could be unpredictable. Further, the cap-on-EN solution depends heavily on external loading of the EN signal... so that solution may stop working in systems where there are a number of devices which share EN or the Host OS DTR-RTS inter-signal latency grows or is variable.
The purpose of this alternative is to also remove this EN signal loading dependency.
Lastly, one could make a similar short circuit complaint about placing a capacitor on EN. The signal which drives it low also has to deal with a short-circuit condition when discharging the cap. In this regard, perhaps the two solutions are not so dissimilar? Remember, EN can be driven by any external circuit, the ESP32 itself, or our little reset circuit. Since there are more places out of our control where this could go wrong (weak external driver) it can lead to more side effects, and in effect the same "short circuit" condition with an actually higher voltage (no extra diode drop).
Thanks for pointing out this additional facet which was not well called out in the write up. It's great to have more eyes looking at these things to find areas for further improvement and deeper explanation.
-
- Posts: 9769
- Joined: Thu Nov 26, 2015 4:08 am
Re: DevKit Auto USB Programming: A New Fix
Yeah, no worries, I'm certainly agreeing that this is a better solution than a big cap on the EN line. Our hardware devs are also looking into this; they certainly seem to be willing to take this improvement (either in the original or in modified form) into account and they'll also run simulations to see if it doesn't affect other bits of the various devboards we have here. If they give me any feedback, I'll keep the information flowing and post it here as well.
Re: DevKit Auto USB Programming: A New Fix
Great!
Glad to hear it's being explored.
100% agree, as I said in my prior reply, it would only take a series resistor with the CAP to solve the problem you present. Doesn't require too much to soften the discharge. Also agree a "TEE" would work as well (in effect the same thing). One would want to prefer more of the current to flow towards keeping the transistor ON, so obviously an imbalanced tee would be best (as you mentioned).
You guys can fiddle with the precise component values and topology.
The long analysis and write up was to serve 3 purposes...
1. To dive deeply into actually understanding and explaining the problem. (rather than tossing noodles at the wall)
2. Motivate "management" to actually examine the problem and perhaps consider this or a similar solution.
(Yes, it's an actual HW bug as it turns out!!)
3. Provide an arguably at least "equivalent" and perhaps more reliable solution for the many people who already have/use these Dev Boards. A solution to this problem that all can agree on (for existing DevKits) would probably cut the volume of traffic on the HW forum by 50%!
The "fix" is pretty easy to implement, and arguably no "worse" than hanging a cap on EN. (either way, you are discharging a full cap into a transistor).
Eager to know what the team at Espressif thinks after examining things further. Also, I'll note, that it's easy to force this problem to happen 100% (and then see it fixed) by embedding the downloader into 1-2 nested VmWare VMs. This causes the space between the signals to be sufficiently large that it's reliably reproduced, and reliably verifiably fixed.
Best Regards!
Glad to hear it's being explored.
100% agree, as I said in my prior reply, it would only take a series resistor with the CAP to solve the problem you present. Doesn't require too much to soften the discharge. Also agree a "TEE" would work as well (in effect the same thing). One would want to prefer more of the current to flow towards keeping the transistor ON, so obviously an imbalanced tee would be best (as you mentioned).
You guys can fiddle with the precise component values and topology.
The long analysis and write up was to serve 3 purposes...
1. To dive deeply into actually understanding and explaining the problem. (rather than tossing noodles at the wall)
2. Motivate "management" to actually examine the problem and perhaps consider this or a similar solution.
(Yes, it's an actual HW bug as it turns out!!)
3. Provide an arguably at least "equivalent" and perhaps more reliable solution for the many people who already have/use these Dev Boards. A solution to this problem that all can agree on (for existing DevKits) would probably cut the volume of traffic on the HW forum by 50%!
The "fix" is pretty easy to implement, and arguably no "worse" than hanging a cap on EN. (either way, you are discharging a full cap into a transistor).
Eager to know what the team at Espressif thinks after examining things further. Also, I'll note, that it's easy to force this problem to happen 100% (and then see it fixed) by embedding the downloader into 1-2 nested VmWare VMs. This causes the space between the signals to be sufficiently large that it's reliably reproduced, and reliably verifiably fixed.
Best Regards!
Re: DevKit Auto USB Programming: A New Fix
I have used many dev kits from all sorts of players in the market. I agree some will go into boot mode, and some wont.
I have had 100% success with simply adding a 0.1uf on IO_0 to GND Never came across a device that this method didn't work.
On other boards that had no cap on EN I would also add a 0.1uf to GND on those in addition to the 0.1uf on IO_0.
I have had 100% success with simply adding a 0.1uf on IO_0 to GND Never came across a device that this method didn't work.
On other boards that had no cap on EN I would also add a 0.1uf to GND on those in addition to the 0.1uf on IO_0.
-
- Posts: 94
- Joined: Tue Sep 07, 2021 12:07 pm
Re: DevKit Auto USB Programming: A New Fix
@MrKenSan3 thanks! Best research and explanation ever. I was stumbling over how that two transistor circuit worked and got lucky and found this post. I definitely had issues with the boot reliability (~25% chance never gets started) when I used 10uF on the En pin. And maybe 1uF, but way less often.
Craige
Who is online
Users browsing this forum: No registered users and 109 guests