#embedded-hal #watchdog #embassy #no-std

no-std task-watchdog

A robust, flexible watchdog management library for embedded systems that multiplexes multiple task watchdogs into a single hardware watchdog timer, preventing system lockups when tasks fail to respond

2 releases

new 0.1.1 Mar 22, 2025
0.1.0 Mar 20, 2025

#116 in Embedded development

46 downloads per month

MIT/Apache

87KB
1.5K SLoC

Rust 1K SLoC // 0.1% comments Alex 161 SLoC Shell 141 SLoC // 0.3% comments

๐Ÿ›ก๏ธ task-watchdog ๐Ÿบ

A robust, flexible watchdog management library for embedded systems that multiplexes multiple task watchdogs into a single hardware watchdog timer, preventing system lockups when tasks fail to respond.

โœจ Key Features

  • ๐Ÿ”„ Hardware Agnostic API: Implements a consistent interface across different embedded microcontrollers with extensible trait system for hardware watchdog and clock types
  • ๐Ÿ”€ Task Multiplexing: Consolidates multiple independent task watchdogs into a single hardware watchdog, triggering if any task fails to check in
  • ๐Ÿ”Œ Dynamic Task Management: Tasks can be registered and deregistered at runtime, allowing for flexible monitoring configurations
  • โšก Async and Sync Support: Works with both synchronous (via device HALs) and asynchronous (Embassy) execution environments
  • ๐Ÿ“ฆ No-Alloc Mode: Functions in both alloc and no_alloc modes for environments with or without heap availability
  • โฑ๏ธ Configurable Timeouts: Individual timeout durations for each registered task
  • ๐Ÿงช no_std Compatible: Designed for resource-constrained embedded environments without an operating system

๐Ÿš€ Quick Start

Examples are provided for async (using embassy-rs) and sync operation of task-watchdog. The async/embassy example supports the Pico, Pico 2 and STM32F103C8 (blue pill). The sync example supports the Pico and Pico 2.

First, install Rust

Add the approriate target(s):

rustup target add thumbv6m-none-eabi         # RP2040/Pico
rustup target add thumbv8m.main-none-eabihf  # RP235x/Pico 2
rustup target add thumbv7m-none-eabi         # STM32

Next, install probe-rs

Now connect your Pico/Pico 2/STM321F103C8 device to a connected debug probe, and run one of:

builds/flash-async-pico.sh
builds/flash-async-pico2.sh
builds/flash-async-stm32f103c8.sh

To understand how to use task-watchdog yourself, check out one of the examples:

For ESP32 support see scripts/README.md.

๐Ÿ“ Usage

The library supports both synchronous and asynchronous APIs with a consistent pattern across both styles.

๐Ÿง  Core Concepts

  • Task Registration: Each monitored task is registered with its own timeout period
  • Feeding: Tasks must feed, or pet, the watchdog within their timeout period to prevent a reset
  • Task Multiplexing: The library efficiently manages multiple task timeouts through a single hardware watchdog, triggering if any individual task fails to check in

Task Watchdog Multiplexing

โšกAsynchronous API (Embassy)

For platforms using Embassy, tasks feed the watchdog asynchronously:

// Setup
let watchdog = WatchdogRunner::new(hw_watchdog, config, EmbassyClock);

// Register tasks with individual timeouts
watchdog.register_task(&MainTask, Duration::from_millis(2000)).await;
watchdog.register_task(&SensorTask, Duration::from_millis(5000)).await;

// Spawn the watchdog task itself
spawner.spawn(watchdog_task(watchdog)).unwrap();

// In your application tasks
async fn main_task(watchdog: &'static WatchdogRunnerType) -> ! {
    loop {
        // Do work...
        watchdog.feed(&MainTask).await;
        Timer::after(Duration::from_millis(1000)).await;
    }
}

// Implement other tasks

See complete example at examples/src/embasy.rs

โš™๏ธ Synchronous API (non-Embassy)

For platforms without an async runtime, manually manage the watchdog in your main loop:

// Setup
let mut watchdog = Watchdog::<TaskId, NUM_TASK_IDS, RpHalTaskWatchdog, RpHalClock>::new(
    hw_watchdog, config, RpHalClock::new(timer)
);

// Register tasks with individual timeouts
watchdog.register_task(&TaskId::Main, RpHalDuration::millis(2000));
watchdog.register_task(&TaskId::Sensors, RpHalDuration::millis(3000));

// Start the watchdog
watchdog.start();

// In your main loop
loop {
    // Feed watchdogs for active tasks
    watchdog.feed(&TaskId::Main);
    
    // Check for starved tasks
    let _ = watchdog.check();
}

See complete example at examples/src/rp-sync.rs

๐Ÿ—๏ธ Platform Support

The crate is designed to be platform-agnostic via trait implementations, but includes first-class support for:

  • RP2040 and RP2350 (Raspberry Pi Pico and Pico 2) via the rp2040/rp2350 features (embassy) and rp2040-hal/rp2350-hal (rp2040-hal/rp235x-hal respectively)
  • Embassy async runtime via the embassy feature

There are many other features - see scripts/build-lib.sh for the valid combinations. The most common are:

  • embassy,rp2040,defmt - Async, Pico with defmt support
  • embassy,rp2350,defmt - Async, Pico 2 with defmt support
  • embassy,stm32,defmt - Async, STM32 with defmt support - you will also need embassy-stm32/your_stm32_board_type

๐Ÿ“œ License

Licensed under either of the following, at your option:

Dependencies

~1โ€“52MB
~1.5M SLoC