5.5.23Embedded Systems & Real-Time Software

Watchdog timers — purpose, feeding, types

3,327 words15 min readdifficulty · medium3 backlinks

Overview

A watchdog timer (WDT) is a hardware timer that automatically resets or interrupts a system if software fails to periodically "feed" it. It's a fault-tolerance mechanism that protects embedded systems from software hangs, infinite loops, and deadlocks.

Figure — Watchdog timers — purpose, feeding, types

In embedded systems, software can "hang" due to bugs, memory corruption, or hardware faults. Without intervention, the system stays frozen indefinitely. A watchdog timer forces the system to either prove it's alive (by resetting the timer) or be automatically restarted.

WHY this matters: Embedded systems often run unattended in critical applications (medical devices, automotive, industrial control). A software hang could be catastrophic. The watchdog provides automatic recovery without human intervention.

The Fundamental Mechanism

HOW it works:

  1. Initialization: Configure WDT with timeout period (e.g., 500ms)
  2. Enable: Start the countdown
  3. Normal operation: Software "feeds" (resets) the timer within timeout period
  4. Fault condition: If software hangs, feeding stops → timer expires → system reset/interrupt
  5. Recovery: System restarts, ideally recovering from the fault

Ttimeout=Nmaxfclock×prescalerT_{timeout} = \frac{N_{max}}{f_{clock}} \times \text{prescaler}

Where:

  • TtimeoutT_{timeout} = timeout period (seconds)
  • NmaxN_{max} = maximum counter value (hardware-dependent, often 16-bit = 65535)
  • fclockf_{clock} = clock frequency feeding the WDT
  • prescaler = clock divider (1, 8, 64, 256, 1024 typical values)

WHY this formula? The watchdog is just a down-counter clocked by a divided system clock. The timeout is how long it takes to count from NmaxN_{max} to 0 at the divided clock rate.

DERIVATION:

  • Counter decrements once per clock cycle at divided frequency
  • Divided frequency: fdivided=fclockprescalerf_{divided} = \frac{f_{clock}}{\text{prescaler}}
  • Time per decrement: Δt=prescalerfclock\Delta t = \frac{\text{prescaler}}{f_{clock}}
  • Total time for NmaxN_{max} decrements: Ttimeout=Nmax×Δt=Nmax×prescalerfclockT_{timeout} = N_{max} \times \Delta t = \frac{N_{max} \times \text{prescaler}}{f_{clock}}

Calculate timeout: Ttimeout=65535128000×1024=67,107,840128000=524.28 seconds8.7 minutesT_{timeout} = \frac{65535}{128000} \times 1024 = \frac{67,107,840}{128000} = 524.28 \text{ seconds}≈ 8.7 \text{ minutes}

Wait, that's too long! Most embedded systems use shorter prescalers. With prescaler = 64: Ttimeout=65535128000×64=32.77 secondsT_{timeout} = \frac{65535}{128000} \times 64 = 32.77 \text{ seconds}

WHY this matters? You choose the prescaler based on how quickly you want recovery. Longer timeout = more tolerance for legitimate long operations. Shorter timeout = faster recovery from hangs but risk false resets during valid long operations.

Types of Watchdog Timers

1. Hardware-Only Watchdog

Characteristics:

  • Independent of CPU core
  • Often uses separate clock source (internal RC oscillator)
  • Reset via dedicated register write or I/O pin toggle
  • Configuration locked at startup or via fuses

Feeding mechanism:

// AVR example - write specific value to WDT register
WDTCSR |= (1 << WDE);  // Enable watchdog
// In main loop:
wdt_reset();  // Clears the timer (inline assembly: __asm__ __volatile__ ("wdr"))

WHY separate clock? If the main clock fails, the system hangs but the watchdog still runs on its independent clock and can trigger a reset.

void setup() { // Configure for 250ms timeout wdt_enable(WDTO_250MS); // Macro sets prescaler bits }

void loop() { // Do work... critical_sensor_read(); compute_control_output(); // Feed watchdog before timeout wdt_reset(); // Must happen within250ms delay(100); // Safe - leaves150ms margin }


**WHY this step?** `wdt_enable()` sets hardware bits that configure the timeout. `wdt_reset()` resets the counter to maximum. If `loop()` hangs in any function, the reset never happens, timer expires, system resets.

> [!mistake] Feeding Too Frequently
> **Wrong approach:**
> ```c
> void loop() {
>     wdt_reset();  // First thing in loop
>     potentially_hanging_function();  // Bug here never detected!
> }
> ```

**WHY this feels right:** "I'll reset the watchdog immediately so I never forget."

**The problem:** If `potentially_hanging_function()` hangs, the watchdog was already reset, so you get a full timeout period before recovery. Worse, if there's a tight loop that bypasses most code but hits the reset, the watchdog never catches the logic error.

**The fix:** Feed the watchdog ==after== critical operations complete successfully, using it as a "heartbeat" that proves the main loop executed fully:
```c
void loop() {
    sensor_read();
    process_data();
    update_outputs();
    
    wdt_reset();  // Only feed if we completed full loop iteration
}

2. Software-Controlled Watchdog

Characteristics:

  • Can be turned off via register writes
  • More configuration options (interrupt vs reset)
  • Less protection against wild pointers or stack corruption

Feeding mechanism:

// STM32 example
HAL_IWDG_Refresh(&hiwdg);  // Reload counter register

WHY allow software control? During debugging, development, or firmware updates, you may need to disable the watchdog. Production systems often use hardware-locked watchdogs.

3. Window Watchdog

Where:

  • TminT_{min} = minimum time before feeding is allowed
  • TmaxT_{max} = maximum time before feeding causes timeout
  • TfeedT_{feed} = actual time when feed occurs

WHY two bounds?

  • Upper bound (TmaxT_{max}): Like normal watchdog, catches hangs
  • Lower bound (TminT_{min}): Catches code running too fast (interrupt storms, tight loops, timing bugs)

DERIVATION of bounds: In hardware, a window watchdog uses two comparators:

  • Counter value compared to upper threshold: Countercurrent<ThresholdupperCounter_{current} < Threshold_{upper} → reset
  • Counter value compared to lower threshold: Countercurrent>ThresholdlowerCounter_{current} > Threshold_{lower} → reset allowed

Time mapping: Countercurrent=Nmaxt×fclockprescalerCounter_{current} = N_{max} - \frac{t \times f_{clock}}{prescaler}

Thus:

  • Tmin=NmaxThresholdlowerfclock×prescalerT_{min} = \frac{N_{max} - Threshold_{lower}}{f_{clock}} \times prescaler
  • Tmax=NmaxThresholdupperfclock×prescalerT_{max} = \frac{N_{max} - Threshold_{upper}}{f_{clock}} \times prescaler

uint32_t last_feed = 0;

void loop() { uint32_t now = HAL_GetTick(); // milliseconds

do_critical_work();

// Feed only in valid window
if (now - last_feed >= 60 && now - last_feed <= 80) {
    HAL_WWDG_Refresh(&hwdg);
    last_feed = now;
}

}


**Scenario - bug caught:** Suppose an interrupt fires every 10ms and calls `loop()`. Without window watchdog, the normaldog gets fed 8 times per80ms period - looks healthy! But the timing is wrong. The window watchdog resets the system because feeding at 10ms is too early, forcing you to fix the timing bug.

**WHY this step?** Window watchdogs enforce not just "is the code running?" but "is the code running at the RIGHT RATE?" This catches timing violations that regular watchdogs miss.

## Watchdog Feeding Strategies

### Strategy 1: Main Loop Heartbeat

```c
void main() {
    wdt_enable(WDTO_500MS);
    
    while(1) {
        task();  // 50ms
        task2();  // 100ms
        task3();  // 50ms
        // Total: ~200ms per iteration
        wdt_reset();  // Heartbeat - proves full loop executed
    }
}

WHY this works? Each feed proves all tasks completed. If any task hangs, the feed doesn't happen, timeout triggers.

Timeout sizing: TtimeoutT_{timeout} > worst-case loop time + margin. Here: 500ms > 200ms + margin.

Strategy 2: Task-Based Feeding (RTOS)

// FreeRTOS example
void watchdog_task(void *param) {
    const TickType_t feed_interval = pdMS_TO_TICKS(200);
    
    while(1) {
        // Check if all critical tasks reported in
        if (task1_alive && task2_alive && task3_alive) {
            wdt_reset();
            task1_alive = false;  // Reset flags
            task2_alive = false;
            task3_alive = false;
        }
        vTaskDelay(feed_interval);
    }
}
 
void critical_task1(void *param) {
    while(1) {
        do_work();
        task1_alive = true;  // Report health
        vTaskDelay(pdMS_TO_TICKS(50));
    }
}

WHY this approach? In RTOS with multiple tasks, the watchdog task only feeds if ALL critical tasks reported in. If any task hangs, the system resets.

DERIVATION of feed interval:

  • Each critical task reports every TtaskT_{task}
  • Watchdog task checks every TcheckT_{check}
  • Timeout must satisfy: Ttimeout>max(Ttask)+Tcheck+marginT_{timeout} > \max(T_{task}) + T_{check} + margin

If task reports every 50ms, watchdog checks every 200ms, timeout should be > 250ms + margin = 500ms.

Problem: How often to feed the watchdog?

Analysis:

  • Longest critical period: Task C at 1000ms
  • Watchdog timeout must be > 1000ms to allow Task C to complete
  • Set timeout = 1500ms (1.5× longest period for margin)
  • Watchdog task runs at 500ms, collects "alive" flags from all tasks
  • Feed only if all flags set since last check

WHY these numbers? Each task sets its flag after successful completion. Watchdog task verifies all tasks ran in the last check period (500ms). But timeout is 1500ms tolerate Task C's 1000ms period. If any task fails for >1500ms, system resets.

WHY this feels right: "If any task is alive, feed the watchdog."

The problem: System can be partially failed. Task1 and Task2 hang, but Task3 keeps running and feeding the watchdog. Critical functions are broken but system doesn't reset.

The fix: Use AND logic - ALL critical tasks must report:

if (task1_alive && task2_alive && task3_alive) {  // AND - correct
    wdt_reset();
}

Strategy 3: Hierarchical Feeding

For complex systems, use multiple watchdogs:

  1. Hardware watchdog (1s timeout): Last resort, catches total system hang
  2. Software watchdog (500ms): Monitors main loop, can generate interrupt before hard reset
  3. Task watchdogs (per-task timeouts): Each critical task has its own monitor

WHY layers? Defense in depth. Inner layers catch problems earlier with more context (interrupt handler can log state before reset). Outer layer guarantees recovery even if inner layers fail.

Watchdog Timer Reset Handling

When a watchdog triggers, the system resets. Firmware must detect this on startup:

#include <avr/wdt.h>
 
void setup() {
    uint8_t reset_source = MCUSR;  // Read reset status register
    MCUSR = 0;  // Clear for next time
    
    if (reset_source & (1 << WDRF)) {
        // Watchdog caused reset
        log_error("WDT reset occurred");
        error_count++;
        
        if (error_count > 3) {
            enter_safe_mode();  // Too many resets, something seriously wrong
        }
    }
    wdt_enable(WDTO_500MS);  // Re-enable watchdog
}

WHY check reset source? Distinguish watchdog resets from power-on, brown-out, or software resets. Track watchdog resets over time to detect chronic reliability issues.

Trecovery=Treset+Tboot+TinitT_{recovery} = T_{reset} + T_{boot} + T_{init}

Where:

  • TresetT_{reset} = hardware reset pulse duration (typically 1-10ms)
  • TbootT_{boot} = bootloader execution time (0ms if no bootloader, or50-500ms)
  • TinitT_{init} = application initialization time (variable, should be minimized)

WHY this matters? In real-time systems, watchdog recovery causes a service interruption of duration TrecoveryT_{recovery}. Design initialization to be as fast as possible while still ensuring safe startup.

DERIVATION: These times add serially because each must complete before the next begins. Minimize each component:

  • TresetT_{reset}: Hardware fixed, typically<10ms
  • TbootT_{boot}: Disable bootloader in production or use fast bootloader
  • TinitT_{init}: Initialize only critical subsystems before feeding first watchdog; defer non-critical init

Target: TrecoveryT_{recovery} < 1 second for most embedded systems.

Practical Considerations

Timeout Selection:

  • Too short: False resets during valid long operations
  • Too long: Slow recovery from actual faults
  • Rule of thumb: TtimeoutT_{timeout} = 2× to 3× nominal loop time

Interrupt vs Reset: Some watchdogs offer interrupt mode: generate interrupt before final reset. Use this to:

  • Log system state for debugging
  • Attempt recovery (clear stuck peripheral, reset state machine)
  • If recovery fails, allow progression to hard reset

Testing Watchdogs: You MUST test that the watchdog actually works:

void test_watchdog() {
    wdt_enable(WDTO_500MS);
    while(1) {
        // Deliberately don't feed - should reset in 500ms
    }
    // Should never reach here
}

WHY test? Misconfigured watchdog gives false confidence. Always verify it triggers in development.

Power Consumption: Watchdogs typically use independent RC oscillators that run in sleep modes. Adds ~1-10µA to sleep current. Factor this into battery life calculations for ultra-low-power designs.

Recall Explain to a12-Year-Old

Imagine you have a little robot that does homework for you. But sometimes, the robot gets confused and freezes up - it just sits there, not doing anything, stuck forever.

A watchdog timer is like setting a kitchen timer for the robot. You tell the robot: "Every 5 minutes, you must come press this button to reset the timer. If you forget, the timer goes BEEP and I'll turn you off and back on to fix you."

Now, when your robot is working properly, every few minutes it thinks "Oh, time to reset that timer!" and presses the button. The timer resets, and everything keeps going.

But if the robot freezes - it can't press the button. The timer keeps counting down... 4 minutes... 3 minutes... 2... 1... BEEP! The timer goes off, which automatically turns the robot off and back on (like unplugging it and plugging it back in). When it restarts, it's not frozen anymore - problem fixed!

The trick is: the robot has to remember to press the button ONLY when it's actually working correctly on homework. If it presses the button while it's stuck in a bad loop (like doing the same math problem wrong over and over), that doesn't help. So you train the robot to only press the button after it finishes a complete homework problem correctly.

That's exactly what embedded systems do with watchdog timers - they make sure the computer is actually working right, and if it freezes, they automatically restart it!

Connections

  • Interrupt Service Routines - Watchdog can generate interrupts before reset
  • Real-Time Operating Systems - RTOS task monitoring with watchdogs
  • Hardware Timer Peripherals - Watchdog uses timer hardware
  • System Reset Sources - Detecting and handling different reset types
  • Fault Tolerance - Watchdog is one layer of fault-tolerant design
  • Brown-Out Detection - Works alongside watchdog for power fault protection
  • Safe State Design - System behavior after watchdog reset
  • Bootloader Design - Watchdog behavior during firmware updates

#flashcards/coding

What is a watchdog timer? :: A hardware timer that automatically resets the system if software fails to periodically "feed" (reset) it, providing protection against software hangs and deadlocks.

Why use an independent clock source for the watchdog?
If the main system clock fails, the watchdog still runs and can trigger a reset, providing protection even against clock failures.
What is a window watchdog?
A watchdog that must be fed within a specific time window - feeding too early OR too late triggers a reset, catching both hangs and runaway code.
What is the formula for watchdog timeout?
Ttimeout=Nmaxfclock×prescalerT_{timeout} = \frac{N_{max}}{f_{clock}} \times \text{prescaler} where NmaxN_{max} is max counter value, fclockf_{clock} is clock frequency, and prescaler is the clock divider.
Why feed the watchdog AFTER critical operations, not before?
Feeding after ensures the operations completed successfully; feeding before gives false health signal if the operation then hangs.

What's the difference between hardware-only and software-controlled watchdog? :: Hardware-only cannot be disabled by software (maximum protection); software-controlled can be enabled/disabled at runtime (more flexible but less protection).

In RTOS, should watchdog feeding use AND or OR logic for task flags?
AND logic - ALL critical tasks must report healthy; OR logic allows partial failures to go undetected.
How to detect if a watchdog caused the last reset?
Read the reset status register (like MCUSR on AVR) and check the watchdog reset flag bit on startup.
What should timeout be relative to loop time?
TtimeoutT_{timeout} should be 2× to 3× the worst-case loop execution time to provide margin while avoiding false resets.
Why might you use interrupt mode before reset?
To log system state for debugging or attempt recovery before the hard reset, providing better diagnostics and possibly avoiding a full reset.

Concept Map

creates risk

prevents

is a

clocked by

set by

must periodically

prevents

triggers

enables

timeout given by

protects

Software hang or bug

System freeze

Watchdog timer

Hardware down-counter

Divided clock

Prescaler

Feed / reset timer

Timer reaches zero

System reset or interrupt

Automatic recovery

Nmax times prescaler over fclock

Unattended critical systems

Hinglish (regional understanding)

Intuition Hinglish mein samjho

Watchdog timer ek bahut important safety mechanism hai jo embedded systems mein use hota hai. Socho ki tumhara microcontroller kisi infinite loop ya deadlock mein fas gaya hai - normal case mein system permanently hang ho jayega aur manually restart karna padega. Lekin critical applications mein jaise medical devices, car electronics, ya industrial machinery, ye acceptable nahi hai.

Watchdog timer ka kaam simple hai:ek hardware counter hai jo continuously count down karta rehta hai. Tumhare software ko regularly is counter ko "feed" karna padta hai (matlab reset karna padta hai). Agar software properly chal raha hai, to har100ms ya 500ms mein (jo bhi configure kiya ho) wo watchdog timer ko reset kar dega. Lekin agar code kahin hang ho gaya, to feeding nahi hogi, counter zero tak pahunch jayega, aur automatically system reset ho jayega - hardware level pe, software ka koi control nahi. Ye bilkul automatic recovery hai.

Window watchdog ek advanced version hai jahan tumhe ek specific time window ke andar feed karna padta hai - na bahut jaldi, na bahut der se. Agar tumne bahut jaldi feed kar diya (matlab code bahut fast loop mein hai jo nahi hona chahiye), to bhi reset ho jayega. Agar bahut late kiya, to bhi reset. Isse timing bugshi catch ho jate hain jo normal watchdog miss kar deta.

Production embedded systems mein watchdog timer mandatory hai kyunki field mein unattended operation mein automatic recovery ka yahi ek reliable tarika hai. Proper timeout selection, strategic feeding points, aur reset handling design karke, tum apne system ko fault-tolerant bana sakte ho - agar kuch galat hua, system khud recover kar lega bina human intervention ke.

Go deeper — visual, from zero

Test yourself — Embedded Systems & Real-Time Software

Connections