Skip to content

CircuitPython crashes with Internal watchdog timer expired. #9428

Open
@wbeebe

Description

@wbeebe

CircuitPython version

Adafruit CircuitPython 9.1.0 on 2024-07-10; ESP32-S3-DevKitC-1-N32R8 with ESP32S3
Board ID:espressif_esp32s3_devkitc_1_n32r8
UID:C7FD1A1E82C7

Code/REPL

import os
import rtc
import time
import ipaddress
import wifi
import socketpool
import board
import microcontroller
import adafruit_ntp
import neopixel
import binascii

from adafruit_httpserver import Server, Request, Response, POST
#
# Global setup
#
SYSNAME = os.uname().sysname
UNIQUE_ID = binascii.hexlify(microcontroller.cpu.uid).decode('utf-8').upper()
SSID = SYSNAME + '-' + UNIQUE_ID[-4:]
led = neopixel.NeoPixel(board.IO38, 1)
led.fill(0x000000)
#
# Connect to a local WiFi access point.
# Because this code is running in a CircuitPython 9 or later environment,
# it requires a settings.toml file be created with at least the following
# six lines:
#
# AP_SSID = "WIFI SSID"
# AP_PASSWORD = "WIFI PASSWORD"
# STATIC_IP = "IP4 dotted IP address"
# GATEWAY = "192.168.0.1"
# TZ_OFFSET = -4
# DEBUG = "True" 
#
# DEBUG can be either True or False.
#
wifi.radio.hostname = SSID
wifi.radio.connect(os.getenv('AP_SSID'), os.getenv('AP_PASSWORD'))
pool = socketpool.SocketPool(wifi.radio)
ntp = adafruit_ntp.NTP(pool, tz_offset = os.getenv('TZ_OFFSET'))
rtc.RTC().datetime = ntp.datetime
server = Server(pool, "/static", debug=os.getenv('DEBUG'))

def get_date():
    dayname = [
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday",
        "Saturday",
        "Sunday",]

    monthname = [
        "January",
        "February",
        "March",
        "April",
        "May",
        "June",
        "July",
        "August",
        "September",
        "October",
        "November",
        "December" ]

    try:
        now = time.localtime()
        return f"{dayname[now.tm_wday]}, {now.tm_mday} {monthname[now.tm_mon-1]} {now.tm_year} - {now.tm_hour:02}:{now.tm_min:02}:{now.tm_sec:02}"
    except Exception as e:
        return f" >>> EXCEPTION {e}"
    
# The HTML page body is a Python 3 'f' string for advanced formatting.
#
# Double curly braces {{ and }} are used when HTML needs single braces for HTML
# page elements such as CSS styling.
#
def webpage():
    global SSID
    font_family = "sans-serif"
    html = f"""
    <!DOCTYPE html>
    <html>
    <head>
    <meta http-equiv="Content-type" content="text/html;charset=utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" href="data:," />
    <style>
    html{{
        font-family: {font_family};
        background-color: #FFFFFF;
        display:inline-block;
        margin: 0px auto;
        text-align: center;
        }}
    h1{{
        color:#D35F8D;
        word-wrap: break-word;
        font-size: 35px;
        }}
    h2{{
        color:#D35F8D;
        word-wrap: break-word;
        font-size: 20px;
        }}
    p{{
        font-size: 1.5rem;
        word-wrap: break-word;
        }}
    button{{
        font-family: {font_family};
        display: inline-block;
        width: 99%;
        border: none;
        border-radius: 4px;
        color: white;
        padding: 16px 40px;
        text-decoration: none;
        font-size: 30px;
        margin: 2px;
        cursor: pointer;
    }}
    .button-red{{
        background-color: #DC143C;
        }}
    .button-green{{
        background-color: #228B22;
        }}
    .button-dark-gray{{
        background-color: #404040;
        }}
    p.dotted {{
        margin: auto;
        width: 90%;
        font-size:
        25px;
        text-align: center;
        }}
    </style>
    </head>
    <body>
        <title>{SSID} LED Control</title>
        <h1>{SSID}</h1>
        <form accept-charset="utf-8" method="POST">
        <button class="button-green" name="LED ON" value="ONG" type="submit">LED ON</button></a>
        <button class="button-red" name="LED ON" value="ONR" type="submit">LED ON</button></a>
        <button class="button-dark-gray" name="LED OFF" value="OFF" type="submit">LED OFF</button></a>
        </form>
        <h2>CircuitPython {os.uname().version}<br/>
        {get_date()}</h2>
    </body>
    </html>
    """
    return html

# Default route
#
@server.route("/")
def base(request: Request):  # pylint: disable=unused-argument
    return Response(request, webpage(), content_type='text/html')

# Determine which button was pressed and
# execute that button's associated action.
#
@server.route("/", POST)
def buttonpress(request: Request):
    raw_text = request.raw_request.decode("utf8")
    #print(raw_text)
    #
    #
    if "ONG" in raw_text:
        led.fill(0x006400)
    #
    #
    if "ONR" in raw_text:
        led.fill(0x640000)
    #
    # If the led off button was pressed...
    if "OFF" in raw_text:
        led.fill(0x000000)

    return Response(request, webpage(), content_type='text/html')

try:
    server.start(str(wifi.radio.ipv4_address))
    print(f" Listening on http://{wifi.radio.ipv4_address}")
#
# If the server fails to start then reset the microprocessor.
# If there is a hardware failure then this can put the software into a
# boot loop. That's why the time.sleep(5) is there so that a Ctrl C can exit
# at the REPL during development.
#
except OSError as e:
    print(f" !!! OSError: {e}")
    print(" !!! OSError Exception, Waiting !!!")
    time.sleep(5)
    print(" !!! OSError Exception, Restarting !!!")
    microcontroller.reset()
#
# DO NOT hard code the while loop as True,
# instead provide a test and exit if something goes wrong.
#
is_healthy = True;

while is_healthy:
    try:
        # Poll for incoming requests.
        server.poll()
    except Exception as e:
        print(f' EXCEPTION {e}')
        is_healthy = False
        continue

Behavior

When left to run unattended the board will stop executing, and any attempt to perform ^D to restart returns the following message at the REPL:

Auto-reload is off.
Running in safe mode! Not running saved code.

You are in safe mode because:
Internal watchdog timer expired.
Press reset to exit safe mode.

Press any key to enter the REPL. Use CTRL-D to reload.

Description

Not only does this occur with the Espressif ESP32-S3 board, but it also occurs with the Raspberry Pi Pico and Pico/W with the same version of CircuitPython. It will also occur with CircuitPython 9.0.5, again with the boards listed above.

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions