Skip to content

CircuitPython crashes with Internal watchdog timer expired. #9428

Closed

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

Activity

  1. dhalbert commented on Jul 13, 2024

    @dhalbert
    Collaborator

    Thanks. Is the failure also Internal watchdog timer expired. on the Pico W?

    The plain Pico doesn't have wifi, so how did you make this run on the Pico? Or is that a typo?

    How long does it take for the safe mode failure to happen?

    Are you using the latest versions of the needed libraries?

  2. wbeebe commented on Jul 13, 2024

    @wbeebe
    Author

    Thanks. Is the failure also Internal watchdog timer expired. on the Pico W?

    Yes it is.

    The plain Pico doesn't have wifi, so how did you make this run on the Pico? Or is that a typo?

    It is a Pico/W only issue. I'm so used to including both versions of the Pico when I write about them. My apologies.

    How long does it take for the safe mode failure to happen?

    I can only say overnight. For example I went to bed around 11pm after checking it was still operational, then when I got up this morning a little after 6 am it was in safe mode.

    Are you using the latest versions of the needed libraries?

    Yes. Whenever I update I always pull the version of the libraries that match the CircuitPython version as well as the release date.

  3. wbeebe commented on Jul 13, 2024

    @wbeebe
    Author

    BTW, this is what the code looks like when it's running. A view of the web page on my iPhone. Nothing fancy at all because I stripped out a lot for this test code.

    IMG_5503

  4. dhalbert commented on Jul 15, 2024

    @dhalbert
    Collaborator

    Could you post a redacted (hide password, SSID, etc.) version of your settings.toml? I am interested in whether you have any CIRCUITPY_... settings, or whether you only have the keys referenced above.

  5. wbeebe commented on Jul 15, 2024

    @wbeebe
    Author
    AP_SSID = "SSID"
    AP_PASSWORD = "PASSWORD"
    TZ_OFFSET = -4
    DEBUG = "False"
    

    Just the four shown above. STATIC_IP and GATEWAY aren't needed, and I need to adjust the comment block accordingly.

  6. added this to the 9.x.x milestone on Jul 15, 2024
  7. modified the milestones: 9.x.x, 10.x.x on Mar 27, 2025
  8. modified the milestones: 10.x.x, 10.3.0 on May 19, 2026
  9. dhalbert commented on Jun 24, 2026

    @dhalbert
    Collaborator

    I believe this is the same potential bug as #9460. I tried reproducing error using the test program in #9460 (comment) on 10.3.0-alpha.3. I tried fetches every 5 minutes and every 1000 seconds (16.67 minutes), and could not reproduce the crash.

    Since this is a really old issue, I'm going to close this for now. If you are still seeing this, could you open a new issuer with a reproducer? Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions