Wiznet makers

ruilixin6

Published August 24, 2026 ©

187 UCC

0 VAR

0 Contests

0 Followers

0 Following

Original Link

Full‑Workflow Analysis of DS1232 External Watchdog Implemented with MicroPython

Full‑process analysis of DS1232 external watchdog driver and experiment based on MicroPython.

COMPONENTS
PROJECT DESCRIPTION

【Preliminary Note】The original hardware example in this article was written based on the RP2040. The actual hardware used in this hands-on demonstration features the W55RP20 as the main controller chip. The circuit logic and UF2 flashing operation principles are universally applicable, with only the main controller model differing. The original chip model mentioned in the circuit descriptions below is provided for reference purposes only.
  1. DS1232 chip driver code design

DS1232 is an external watchdog chip for hardware reset protection of MCU. Driver objectives:

Output WDI (Watchdog Input) pulses through MCU GPIO pins.

Toggle WDI pin periodically to prevent DS1232 from resetting MCU upon timeout.

Provide two feeding modes: automatic feeding (Timer‑based) and manual feeding (kick).

Support stop‑feeding (stop) for reset test or safe‑reset scenarios.

Deliver simple‑to‑use, stable, reliable and ISR‑safe application interfaces.

Driver source code:

# Python env   : MicroPython v1.23.0
# -*- coding: utf-8 -*-        
# @Time    : 2025/8/25 6:46 PM   
# @Author  : Li Qingshui            
# @File    : ds1232.py       
# @Description : Driver for external DS1232 watchdog module
# ======================================== Import related modules =========================================
# Import hardware‑related modules
from machine import Pin, Timer
# ======================================== Global variables ============================================
# ======================================== Function definitions ============================================
# ======================================== Custom classes ============================================
class DS1232:
    """
    This class controls external DS1232 watchdog module. It toggles WDI pin periodically to avoid MCU reset.
    Attributes:
        wdi (Pin): machine.Pin instance for watchdog feed pulses.
        state (int): Current WDI output state, either 0 or 1.
        timer (Timer): machine.Timer instance for periodic feed operations.
    Methods:
        __init__(wdi_pin: int, feed_interval: int = 1000) -> None: Initialize watchdog and start automatic feeding.
        stop() -> None: Stop automatic feeding and pull WDI pin low.
        kick() -> None: Manually feed watchdog, toggle WDI pin once immediately.
    Notes:
        - Timer object is created upon instantiation for periodic WDI toggling.
        - _feed is internal callback, do not call it directly.
        - Most class methods are not ISR‑safe; Timer callback _feed is ISR‑safe.
        - After stop(), WDI pin stays low, DS1232 will reset MCU after timeout.

    DS1232_Watchdog driver for controlling an external DS1232 watchdog module.
    Periodically toggles WDI pin to prevent MCU reset.
    Attributes:
        wdi (Pin): machine.Pin instance for feeding pulses.
        state (int): Current WDI output state, 0 or 1.
        timer (Timer): machine.Timer instance for periodic feeding.
    Methods:
        __init__(wdi_pin: int, feed_interval: int = 1000) -> None: Initialize the watchdog and start automatic feeding.
        stop() -> None: Stop automatic feeding and set WDI low.
        kick() -> None: Manually feed the watchdog by toggling WDI once.
    Notes:
        - Initializes a Timer to periodically toggle WDI.
        - _feed is an internal callback method, not recommended for direct user call.
        - Most methods are not ISR‑safe; _feed callback is ISR‑safe.
        - After stop(), WDI remains low; DS1232 will reset MCU on timeout.
    """
    def __init__(self, wdi_pin: int, feed_interval: int = 1000) -> None:
        """
        Initialize DS1232 watchdog.
        Args:
            wdi_pin (int): WDI pin number.
            feed_interval (int): Feed interval in milliseconds. Default value is 1000ms.
        Returns:
            None
        Raises:
            ValueError: When wdi_pin is not integer or feed_interval > 1000.
            RuntimeError: When Timer initialization fails.
        Notes:
            Automatic feed starts immediately after object creation.
            Uses timer resource, not ISR‑safe.

        Initialize DS1232 watchdog.
        Args:
            wdi_pin (int): WDI pin number.
            feed_interval (int): Feeding interval in ms. Default is 1000ms.
        Returns:
            None
        Raises:
            ValueError: If wdi_pin is not an integer or feed_interval > 1000 ms.
            RuntimeError: If Timer initialization fails.
        Notes:
            Feeding starts immediately after object creation.
            Uses Timer resource, not ISR‑safe.
        """
        # Parameter validation
        if not isinstance(wdi_pin, int):
            raise ValueError("wdi pin must be an integer")
        if feed_interval > 1000:
            raise ValueError("feed_interval must be less than 1000ms")
        self.wdi = Pin(wdi_pin, Pin.OUT)
        # Current output state
        self.state = 0
        self.timer = Timer(-1)
        # Start timer for periodic feed operations
        self.timer.init(period=feed_interval, mode=Timer.PERIODIC, callback=self._feed)

    def _feed(self, t: Timer) -> None:
        """
        Timer callback function: toggle WDI pin periodically.
        Args:
            t (Timer): Timer object which triggers this callback.
        Returns:
            None
        Raises:
            None
        Notes:
            Internal method, users should not call directly.
            Executes inside interrupt context, ISR‑safe.

        Timer callback: toggle WDI pin periodically.
        Args:
            t (Timer): Timer instance triggering this callback.
        Returns:
            None
        Raises:
            None
        Notes:
            Internal method, not recommended for direct user call.
            Runs in interrupt context, ISR‑safe.
        """
        # Toggle between 0 / 1
        self.state ^= 1
        self.wdi.value(self.state)

    def stop(self) -> None:
        """
        Stop automatic watchdog feeding.
        Args:
            None
        Returns:
            None
        Raises:
            RuntimeError: When timer de‑initialization fails.
        Notes:
            After stop, WDI pin stays low, DS1232 will reset MCU after timeout.

        Stop automatic feeding.
        Args:
            None
        Returns:
            None
        Raises:
            RuntimeError: If timer deinitialization fails.
        Notes:
            WDI pin is held low after stopping, DS1232 will reset MCU on timeout.
        """
        self.timer.deinit()
        self.wdi.value(0)

    def kick(self) -> None:
        """
        Manual feed operation: toggle WDI pin once immediately.
        Args:
            None
        Returns:
            None
        Raises:
            RuntimeError: When pin write operation fails.
        Notes:
            Usually used for temporary feed or manual feed after stopping auto‑feed.

        Manually feed watchdog by toggling WDI once.
        Args:
            None
        Returns:
            None
        Raises:
            RuntimeError: If pin write fails.
        Notes:
            Useful for temporary feeding or manual feeding after stopping auto mode.
        """
        self.state ^= 1
        self.wdi.value(self.state)
# ======================================== Initialization ==========================================
# ======================================== Main program ===========================================

During initialization, pass WDI pin number and feed interval. The DS1232 class automatically creates GPIO object and starts timer to implement periodic feed operations and prevent MCU reset under normal runtime.

DS1232 class main methods: _feed is internal timer callback for automatic WDI toggling; kick performs manual feed; stop disables automatic feeding so DS1232 will reset MCU after timeout.

Application workflow after creating DS1232 instance:

  1. Timer starts and invokes _feed every feed_interval ms.
  2. _feed toggles WDI → DS1232 watchdog counter gets cleared.
  3. MCU runs normally → kick() can be called for manual feed.
  4. For test or reset purpose → call stop() → WDI pulled low → DS1232 times out → MCU gets reset.
  5. Application experiment

Sample code below initializes DS1232 watchdog, performs periodic feed, detects reset signal and observes MCU reset flow under simulated timeout or manual stop‑feed condition.

Hardware setup: insert Elegance‑One Grove Expansion Board onto Elegance‑One Universal Compatible Expansion Board. Connect GraftSense‑DS1232 watchdog module to UART1 port on Grove expansion board using HY2.0‑4P cable.

Wiring table:

Short‑circuit solder pads for TD and TOL on the back side of GraftSense‑DS1232 watchdog module are both soldered to VCC.

3.png

Source code can be found inside resource package under elegance‑devkit v1\Demo\75 WDG_EXT.

Sample code:

# Python env   : MicroPython v1.23.0
# -*- coding: utf-8 -*-        
# @Time    : 2025/8/25 6:46 PM   
# @Author  : Li Qingshui            
# @File    : main.py       
# @Description : Test program for external DS1232 watchdog module
# ======================================== Import related modules =========================================
# Import hardware‑related modules
from machine import Pin, Timer
# Import time‑related modules
import time
# Import DS1232 watchdog module
from ds1232 import DS1232
# ======================================== Global variables ============================================
# GPIO connected to DS1232 WDI pin
WDI_PIN = 4
# GPIO connected to DS1232 RST pin
RST_PIN = 5
# Feed interval in milliseconds
FEED_INTERVAL = 300
# Delay time before stopping feed operation, unit ms
STOP_FEED_DELAY = 10000
# Global object declaration
wdg = None
stop_feed_timer = None
# Global flag: detect whether RST has been triggered
system_reset_flag = False
# ======================================== Function definitions ============================================
def rst_callback(pin: Pin) -> None:
    """
    DS1232 RST pin interrupt callback function.
    Args:
        pin (Pin): GPIO pin which triggers this callback.
    Returns:
        None
    """
    global system_reset_flag
    # Set flag, main loop will detect and break
    system_reset_flag = True
    print("DS1232 RST pin triggered.")

def stop_feed_callback(t: Timer) -> None:
    """
    Timer callback: stop automatic feed, simulate feed‑failure induced reset.
    Args:
        t (Timer): Timer object
    Returns:
        None
    """
    global wdg, stop_feed_timer
    print("Stop feeding watchdog.")
    # Stop watchdog feeding
    wdg.stop()
    # De‑initialize this one‑shot timer
    stop_feed_timer.deinit()
# ======================================== Custom classes ============================================
# ======================================== Initialization ==========================================
# 3‑second power‑on stabilization delay
time.sleep(3)
# Print debug info
print("FreakStudio:: DS1232 Watchdog Test Program.")
# Initialize DS1232 watchdog
wdg = DS1232(wdi_pin=WDI_PIN, feed_interval=FEED_INTERVAL)
# Perform one manual feed immediately
wdg.kick()
# Configure RST pin as input with pull‑up and attach interrupt callback
rst_pin = Pin(RST_PIN, Pin.IN, Pin.PULL_UP)
rst_pin.irq(trigger=Pin.IRQ_FALLING, handler=rst_callback)
# Create one‑shot timer for delayed feed‑stop action
stop_feed_timer = Timer()
stop_feed_timer.init(period=STOP_FEED_DELAY, mode=Timer.ONE_SHOT, callback=stop_feed_callback)
# ======================================== Main program ===========================================
print("Start feeding watchdog.")
try:
    # Infinite main loop
    while True:
        # Print timestamped log
        current_time = time.ticks_ms()
        print(f"System running... Time: {current_time} ms")
        # Check reset trigger flag
        if system_reset_flag:
            print("System starting reset...")
            # Exit while‑loop
            break
        time.sleep(1)
except KeyboardInterrupt:
    print("Program interrupted.")
finally:
    # Stop watchdog feed
    wdg.stop()
    # Release timer resource
    stop_feed_timer.deinit()

Workflow explanation: After power‑on, MCU waits 3 seconds for stable boot, prints debug information and instantiates DS1232 object to initialize WDI pin and timer for automatic periodic feeding. Call kick() for an immediate manual toggle on WDI to start watchdog timing. Configure RST pin as pull‑up input and bind interrupt callback to detect DS1232 timeout reset signal. Start one‑shot timer to delay stopping automatic feeding and simulate feed‑failure scenario. Program enters main loop:

  1. Print system runtime timestamp (millisecond resolution) every second.
  2. Check system_reset_flag. If RST interrupt is triggered, print reset hint and break main loop.
  3. Catch KeyboardInterrupt for manual program abort. Upon loop exit, finally block stops DS1232 automatic feeding and releases timer resources to guarantee safe MCU and timer state, completing full watchdog test procedure.

Flash firmware and open terminal. Runtime output:

Normal program execution flow:

6.png

After reboot, even when MCU keeps sending valid feed pulses to watchdog chip, pressing hardware RST button on watchdog module still triggers reset. This design delivers reliable external hard‑reset path: when software runs wild or manual board reboot is needed, hardware manual reset has highest priority.

Documents
Comments Write