Reliably reset ESP8266?

All ESP8266 boards running MicroPython.
Official boards are the Adafruit Huzzah and Feather boards.
Target audience: MicroPython users with an ESP8266 board.
Post Reply
cefn
Posts: 230
Joined: Tue Aug 09, 2016 10:58 am

Reliably reset ESP8266?

Post by cefn » Sat Jul 15, 2017 9:21 am

It would be useful for reasons of memory fragmentation to periodically reboot our text adventure nodes.

They maintain no state, but loading each one of our text-adventure 'Jinja-style' templates can slowly eat away at memory, and if there are too many templates, it eventually becomes too low. This is placing a limit on the size of our text adventures, and resetting periodically would resolve this outright.

Unfortunately, the routine I wrote to use machine.reset() when gc.mem_free() gets too low seems unreliable. If I manually CTRL+C the running _boot.py routine and interactively test the machine.reset() function on our nodes, it mostly works fine, but sometimes you see the following on the Serial Console which finishes in a total hang...

Code: Select all

LOW MEMORY, REBOOTING
bcn 0
del if1
usl
Visiting box 3

 ets Jan  8 2013,rst cause:2, boot mode:(1,7)


 ets Jan  8 2013,rst cause:4, boot mode:(1,7)

wdt reset
In the real system (where the machine.reset is inline with a gc.mem_free() test in the loop of our application) this failure case seems to 100%.

Interestingly the text "Visiting box 3" is actually from a few lines later than the machine.reset() request, suggesting that things are running on for some reason.

These nodes maintain a single hardware SPI and a single software SPI to a screen and RFID reader, but have no explicit interrupts or sleep management in place. The VFS and Wifi lines in _boot.py are commented out, and we are running exclusively from a frozen filesystem. However, even with this special configuration I would expect reboots to repeat the behaviour of the first boot.

Can anyone suggest a configuration which is more reliable, or a hardware/software workaround for the confused state which prevents the node from coming back up?

We have been targeting 1.8.7 as this system has been in testing for a long time, (I fear other compatibility issues if we migrate), but if there are known fixes in 1.9.x we will have to rebuild our toolchain against the latest if there are no other workarounds we can try.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Reliably reset ESP8266?

Post by pythoncoder » Sat Jul 15, 2017 9:30 am

In this thread https://github.com/micropython/micropython/issues/3195 @Damien said "Soft reset doesn't work well on the esp8266. I'd suggest you do a hard reset of the device in between each development cycle."

So the question which comes to mind is whether "machine.reset()" is more akin to a hard reset (as per the docs) or a soft reset (which seems to be implied by your experience of retained state).
Peter Hinch
Index to my micropython libraries.

cefn
Posts: 230
Joined: Tue Aug 09, 2016 10:58 am

Re: Reliably reset ESP8266?

Post by cefn » Sat Jul 15, 2017 12:19 pm

I am happy for it to be as hard a reset as possible, but I've struggled to achieve it.

Should I conclude this is impossible through software without external hardware to depower then repower it?

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Reliably reset ESP8266?

Post by Roberthh » Sat Jul 15, 2017 4:39 pm

You can connect a GPIO to the reset input and pull it low. Do not use GPIO 0, 2 or 15. Like:

Code: Select all

from machine import Pin
rst=Pin(5, mode=Pin.OUT, value=1)

# ....
# ....

rst(0)

cefn
Posts: 230
Joined: Tue Aug 09, 2016 10:58 am

Re: Reliably reset ESP8266?

Post by cefn » Sun Jul 16, 2017 4:07 pm

Thanks RobertHH. That is a very handy trick which I will wire into future nodes, assuming I have the spare pin!

The routine I have arrived at successfully executes machine.reset(). It may be because the stack frame in which the memory error was encountered is dropped and the machine.reset() call is in an except clause which can rely on at least a bit of free memory...or something. It's a bit mystifying but it's suddenly started working without failures now.

So the code for the Text Adventure Node fuzz tester now looks like below. It pretends to be all Text Adventure boxes, and fuzzes itself with a random player walking between boxes, and can successfully reset when memory runs out. Takes a long time to happen, but still it's important that it's zero touch once installed.

Incidentally there is now a wire between NodeMCU D0/GPIO16 and RESET (beneath the board in a build I can't now get to), but I don't think it is relevant as there is no code which triggers it.

Code: Select all

from machine import reset

def fuzz():
	...blah blah blah

try:
    fuzz()
except MemoryError:
    reset()

pfalcon
Posts: 1155
Joined: Fri Feb 28, 2014 2:05 pm

Re: Reliably reset ESP8266?

Post by pfalcon » Wed Jul 19, 2017 8:29 pm

machine.reset() is as "hard" reset as possible - it calls vendor function to perform such reset, and it works as good or as bad as the vendor implemented it. One caveat I have suspicion about is that all the magic DTR, etc. machinery modern ESP8266 boards have to ease programming play bad tricks with reset. Literally, my suspicion that extra components on these boards (and/or state of DTR, etc, lines from the host) may cause ESP8266 go into bootloader mode on reset (or possibly just glitch it into a weird state). I never got to verify that hypothesis, so feel free to do that - e.g., try and see how it works with a raw module like ESP-07 or ESP-12, or attach logic probe/scope to GPIO0 and other strapping pins and see what happens there when you issue machine.reset().

As a final note, I believe there's an errata for some silicon revision of ESP32 which says that it may hang on boot (aka reset). And that's ESP32, which is order of magnitude better maintained than ESP8266 was - for example, its bugs are tracked as errata. You can try to extrapolate that to ESP8266 - it also has bugs, just not documented.
Awesome MicroPython list
Pycopy - A better MicroPython https://github.com/pfalcon/micropython
MicroPython standard library for all ports and forks - https://github.com/pfalcon/micropython-lib
More up to date docs - http://pycopy.readthedocs.io/

Post Reply