Skip to content

Concepts First

  • Watchdog (WDG): like a supervisor — the program must periodically "feed" it (reset the counter); if the program hangs, the watchdog resets the system.
  • Counter/compare value: the watchdog clock keeps counting; if it reaches comp_val without a feed, an interrupt or reset fires.
  • Clock source: the watchdog can use BCLK/32K/1K/XTAL; the example iterates over them to verify the actual timing.

Example Overview

This page is based on the wdg_clksource_check example in the official Bouffalo SDK (examples/peripherals/wdg/wdg_clksource_check), which demonstrates the watchdog timer and clock-source verification:

  • Watchdog clock = clock source / (divider + 1); the example iterates over BCLK, 32K, 1K, XTAL;
  • For each source: configure → reset the counter → start → delay 200 ms → read the counter → stop, repeated 10 times;
  • Comparing the counts verifies whether the watchdog timing matches the theoretical frequency.
  • Sibling examples (examples/peripherals/wdg/): wdg_int (interrupt mode), wdg_reset (reset mode).

Operation Steps

1
Enter the Example Directory

No external wiring is needed for this page. Open a terminal and enter the watchdog example directory (prerequisite: set up the environment as in Quick Start (Linux) or Windows):

cd examples/peripherals/wdg/wdg_clksource_check
2
Build the Project

Run the build command. The Ai-M62 (BL616) and Ai-M61 (BL618) belong to the same series, so both use bl616:

make CHIP=bl616 BOARD=bl616dk
3
Flash the Firmware

Connect the board with a USB cable, hold the BOOT button (IO2 on the Ai-M61-32S-Kit), briefly press EN/RST to enter download mode, then flash (replace the serial port with the one on your computer):

make flash CHIP=bl616 COMX=/dev/ttyUSB0
4
Run and Verify

Open a serial tool (baud rate 2000000). The example starts the watchdog with BCLK/32K/1K/XTAL clock sources in turn; each time it delays 200 ms, reads the counter, and prints Delay 200ms, div = x, test x times, cnt: xxx, ending with case success.

Code Execution Flow

The complete execution flow from startup to running is shown below (loop arrows mean repeated execution):

APIs Used by the Example

bflb_device_get_by_name("watchdog0")

Gets the watchdog device handle; "watchdog0" on BL616/BL618.

Parameters:

  • name: device name, always "watchdog0"

Return: struct bflb_device_s * device handle (NULL on failure)

bflb_wdg_init(wdt, config)

Initializes the watchdog. In struct bflb_wdg_config_s:

  • clock_source: WDG_CLKSRC_BCLK / WDG_CLKSRC_32K / WDG_CLKSRC_1K / WDG_CLKSRC_XTAL
  • clock_div: divider; counting clock = source / (div + 1)
  • comp_val: compare value, 0xffff in the example
  • mode: WDG_MODE_INTERRUPT

Parameters:

  • wdt: watchdog device handle
  • config: pointer to the config struct

Return: 0 on success; negative error code on failure

bflb_wdg_reset_countervalue(wdt)

Resets the watchdog counter (i.e. "feed the dog").

Parameters:

  • wdt: watchdog device handle

Return: none

bflb_wdg_start / bflb_wdg_stop(wdt)

Starts/stops the watchdog. Once started, the counter must be reset before the compare value expires, or the system resets/interrupts.

Parameters:

  • wdt: watchdog device handle

Return: none

bflb_wdg_get_countervalue(wdt)

Reads the current counter value to verify timing.

Parameters:

  • wdt: watchdog device handle

Return: counter value

Complete Code

The complete source below matches the effect described on this page. It is based on the official example (examples/peripherals/wdg/wdg_clksource_check); the LED pins are adapted to the Ai-M61/62-32S-Kit onboard RGB LED. Collapsed by default, click to expand:

📜 Click to expand wdg_clksource_check/main.c full code
c
#include "bflb_mtimer.h"
#include "bflb_wdg.h"
#include "board.h"
#include <assert.h>

#if !defined(BL702L)
uint8_t wdg_clk_src_type[] = {
    WDG_CLKSRC_BCLK,
    WDG_CLKSRC_32K,
    WDG_CLKSRC_1K,
    WDG_CLKSRC_XTAL,
};
#else
uint8_t wdg_clk_src_type[] = {
    WDG_CLKSRC_32K,
    WDG_CLKSRC_1K,
    WDG_CLKSRC_XTAL,
};
#endif

int main(void)
{
    uint32_t i = 0;
    uint32_t j = 0;
    uint32_t cnt = 0;

    board_init();
    printf("Timer clksource check\n");

    struct bflb_device_s *wdt;
    wdt = bflb_device_get_by_name("watchdog0");
    assert(wdt != NULL);

    /* watchdog clk = clock_source/(div + 1)*/
    struct bflb_wdg_config_s cfg;
    cfg.clock_source = WDG_CLKSRC_32K;
    cfg.clock_div = 0;
    cfg.comp_val = 0xffff;
    cfg.mode = WDG_MODE_INTERRUPT;

    for (i = 0; i < sizeof(wdg_clk_src_type) / sizeof(wdg_clk_src_type[0]); i++) {
        cnt = 0;

        if (wdg_clk_src_type[i] == WDG_CLKSRC_XTAL) {
            printf("Watchdog Src Clk is XTAL\r\n");
            cfg.clock_div = 199;
        } else if (wdg_clk_src_type[i] == WDG_CLKSRC_32K) {
            printf("Watchdog Src Clk is 32K\r\n");
            cfg.clock_div = 1;
        } else if (wdg_clk_src_type[i] == WDG_CLKSRC_1K) {
            printf("Watchdog Src Clk is 1K\r\n");
            cfg.clock_div = 1;
        }
#if !defined(BL702L)
        else if (wdg_clk_src_type[i] == WDG_CLKSRC_BCLK) {
            printf("Watchdog Src Clk is BCLK\r\n");
            cfg.clock_div = 249;
        }
#endif
        else {
            printf("Other clock, not test.\r\n");
            continue;
        }

        cfg.clock_source = wdg_clk_src_type[i];
        bflb_wdg_init(wdt, &cfg);

        for (j = 0; j < 10; j++) {
            bflb_wdg_reset_countervalue(wdt);
            bflb_wdg_start(wdt);
            bflb_mtimer_delay_ms(200);
            cnt = bflb_wdg_get_countervalue(wdt);
            bflb_wdg_stop(wdt);
            bflb_mtimer_delay_ms(10);
            printf("Delay 200ms, div = %lu, test %lu times, cnt: %lu\r\n", cfg.clock_div + 1, j, cnt);
        }
    }
    printf("case success.\r\n");
    while (1) {
        bflb_mtimer_delay_ms(1500);
    }
}

FAQ

The program keeps resetting

The watchdog resets the system if it is not fed in time. This example is a verification (start/stop) demo; in a real project, call bflb_wdg_reset_countervalue periodically in the main loop or idle task.

The counter does not match the theory

Count = source frequency / (div + 1) × time. Confirm the actual frequency of the source (XTAL = 40 MHz, 32K = 32768 Hz) and the clock_div value.

How to make the watchdog truly reset the system

Set mode to a reset mode (e.g. WDG_MODE_RESET, see bflb_wdg.h) and configure a suitable comp_val timeout.

Have questions?

For any other questions, visit the unified Q&A and discussion board: Ai-Thinker Discussions

Released under the MIT License. Build Time 2026-09-11 14:52:23