circuitpython: Some ESP32-S2 8.0.0-beta code enters safe mode. 7.3.3 does not. Pico W does not.
CircuitPython version
Adafruit CircuitPython 8.0.0-beta.6-40-gcc6dbb373 on 2023-01-16; Adafruit QT Py ESP32S2 with ESP32S2
# and earlier betas... not sure when it started, but at least back to October or so
Code/REPL
import time
import random
import traceback
import board
import digitalio
import neopixel
import wifi
import socketpool
import ssl
from adafruit_httpserver.server import HTTPServer
from adafruit_httpserver.request import HTTPRequest
from adafruit_httpserver.response import HTTPResponse
from adafruit_httpserver.methods import HTTPMethod
from adafruit_httpserver.mime_type import MIMEType
import adafruit_requests
from secrets import secrets
PORT = 8080
URLS = ("http://wifitest.adafruit.com/testwifi/index.html",
"https://httpbin.org/get", )
ONE_SECOND_NS = 1_000_000_000
FIVE_MINUTES_NS = 300_000_000_000
def get_led():
led = None
if hasattr(board, "LED"):
led = digitalio.DigitalInOut(board.LED)
else:
print(f"No LED")
if led: led.switch_to_output(False)
return led
def get_pix():
pix = []
num_pix = 1
if hasattr(board, "NEOPIXEL"):
import neopixel
pix = neopixel.NeoPixel(board.NEOPIXEL, num_pix, brightness=0.25, pixel_order=neopixel.GRB)
elif hasattr(board, "APA102_SCK"): # UMFeatherS2; FunHouse & Itsy Bitsy M4 also have DOTSTAR_CLOCK
import adafruit_dotstar
pix = adafruit_dotstar.DotStar(board.APA102_SCK, board.APA102_MOSI, num_pix, brightness=0.25)
else:
print(f"No NeoPixel. No Dotstar")
if pix: pix[0] = 0
return pix
def connect():
if pix: pix[0] = (0, 255, 255) # green-blue when connecting
print(f"{time.monotonic_ns()} Connected? ", end="")
consecutive_connect_errors = 0
while not wifi.radio.ipv4_address: # check for 0.0.0.0 ...
try:
print(f"Connecting... ", end="")
wifi.radio.connect(secrets["ssid"], secrets["password"])
except ConnectionError as e:
consecutive_connect_errors += 1
print(f"ConnectionError: {e} consecutive={consecutive_connect_errors}", end=" ")
time.sleep(1)
if consecutive_connect_errors > 8:
print(f"Too many consecutive connect failures. Reloading...")
supervisor.reload()
time.sleep(0.0100) # Pico W wifi.radio.ipv4_address can lag wifi.radio.connect by tens of ms
print(f"{wifi.radio.ipv4_address} ", end="")
if hasattr(wifi.radio, "ap_info.rssi") and wifi.radio.ap_info:
time.sleep(1) # ap_info takes a moment to be valid
print(f"RSSI={wifi.radio.ap_info.rssi} ", end="")
print()
if pix: pix[0] = 0
def poll():
if not wifi.radio.ipv4_address:
connect()
if pix: pix[0] = (255, 0, 255) # violet for polling
try:
server.poll()
except Exception as ex:
traceback.print_exception(ex, ex, ex.__traceback__)
if pix: pix[0] = 0
def get_url(url):
if not wifi.radio.ipv4_address:
connect()
if pix: pix[0] = (0, 0, 255) # blue for requests
try:
with requests.request("GET", url, timeout=5,) as r:
print(f"\n{time.monotonic_ns()} {r.status_code} {r.reason.decode('utf-8', 'ignore')} {r.headers}")
except Exception as e:
traceback.print_exception(e, e, e.__traceback__)
if pix: pix[0] = 0
led = get_led()
pix = get_pix()
connect()
pool = socketpool.SocketPool(wifi.radio)
server = HTTPServer(pool)
server.start(str(wifi.radio.ipv4_address), port=PORT)
requests = adafruit_requests.Session(pool, ssl.create_default_context())
@server.route("/")
def base(request: HTTPRequest):
with HTTPResponse(request, content_type=MIMEType.TYPE_HTML) as response:
print(f"\n{time.monotonic_ns()} Serving route...")
response.send_file("index.html")
one_second_start = time.monotonic_ns() - ONE_SECOND_NS
five_minute_start = time.monotonic_ns() - FIVE_MINUTES_NS
while True:
if (time.monotonic_ns() - one_second_start) >= ONE_SECOND_NS:
if led: led.value = not led.value
print(f"{time.monotonic_ns()} Listening on http://{wifi.radio.ipv4_address}:{PORT}", end="\r")
one_second_start = time.monotonic_ns()
try:
poll()
except OSError as e:
traceback.print_exception(e, e, e.__traceback__)
if (time.monotonic_ns() - five_minute_start) >= FIVE_MINUTES_NS:
print(f"\n{time.monotonic_ns()} Requesting url...")
url = random.choice(URLS)
get_url(url)
five_minute_start = time.monotonic_ns()
Behavior
8.0.0-beta code on ESP2-S2 enters safe mode under certain circumstances I can’t identify exactly.
Same projects on ESP32-S2 7.3.3 never enter safe mode. Same projects on Pico W never enter safe mode.
Characteristics of projects entering safe mode:
- always involves httpserver (possibly httpserver combined with requests)
- several relatively-complex requests-only (no httpserver) projects never enter safe mode
- doesn’t seem to matter if httpserver ever serves any routes
- web workflow on or off doesn’t seem to matter (lately I’ve been testing with web workflow off)
- async or not doesn’t seem to matter, though for a long time I though it might since one async webclient-only (no httpserver) project also goes into safe mode (lately I’ve been testing projects reverted away from async)
- presence or absence of
boot.py
doesn’t seem to matter - library versions don’t seem to matter - this has been occurring for months (latest tests using 20230110)
- various versions and rewrites to try to get a minimal example all go into safe mode - finally got a shareable code example (above) that’s still somewhat large and probably has features it doesn’t need, but when I’ve made it too simple it doesn’t enter safe mode (I’ll keep trying to simplify the example)
Behavior: after some indeterminate duration (typically some hours)…
Usually:
You are in safe mode because: CircuitPython core code crashed hard. Whoops! Crash into the HardFault_Handler.
Occasionally:
You are in safe mode because: Internal watchdog timer expired.
I just started up 4 with the above code a half hour ago, fresh from a reset, and three have crashed: two hardfault and one internal watchdog. It always enters safe mode after the “Listening on http://…” print statement, most likely in server.poll()
, and if so then most likely in _sock.accept()
.
Description
No response
Additional information
No response
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 28 (16 by maintainers)
Please re-test after idf 5 upgrade