Watchdog Timer Calculator

Calculate IWDG prescaler and reload values for STM32, CRV register for nRF52, and watchdog configuration for RP2040 and ESP32.

Parameters

MCU / Watchdog

Nominal LSI — varies ±20%, check with LSI calibration

Target timeout

Result

IWDG_PR

3

/32 prescaler

IWDG_RLR

2499

0x09C3

Nominal timeout2.000 s

LSI ±20% tolerance band

Fastest (LSI +20%)1.667 s
Slowest (LSI −20%)2.500 s
C register configuration
IWDG->KR  = 0x5555;  // unlock PR/RLR
IWDG->PR  = 3;       // prescaler /32
IWDG->RLR = 2499;    // reload → 2.000 s nominal
IWDG->KR  = 0xAAAA;  // refresh (pet)
IWDG->KR  = 0xCCCC;  // start watchdog

// To pet in main loop:
// IWDG->KR = 0xAAAA;

Common Watchdog Timeouts

ApplicationTimeoutReasoning
Simple bare-metal loop100 msPetted every 10–50 ms
RTOS task watchdog5 sTask period + margin
BLE advertising cycle2 s1 s adv interval + margin
LoRa TX/RX window10 sWorst-case airtime
Over-the-air update30 sFlash write time

How watchdog timers work

A watchdog timer is a free-running counter that resets the MCU if firmware fails to reload it within a configured timeout. The firmware must periodically write a specific value to a reload register (commonly called “petting” or “kicking” the watchdog). If the main loop hangs, blocks on a mutex forever, or hits a hard fault that doesn’t reach the pet code, the counter expires and the device resets cleanly.

The hardware is intentionally simple. On most MCUs it is a down-counter clocked by a dedicated oscillator, independent of the main system clock. That independence is the point: the watchdog keeps running even if the main PLL crashes or enters a bad state.

STM32 IWDG — unlock sequence and LSI inaccuracy

The IWDG peripheral on STM32 requires a specific key sequence before you can write the prescaler (PR) or reload (RLR) registers. Writing 0x5555 to IWDG->KR unlocks write access. Without this, writes to PR and RLR are silently ignored — a common source of confusion when migrating from HAL to bare-metal code.

IWDG->KR  = 0x5555;  // unlock
IWDG->PR  = 4;       // /64 prescaler
IWDG->RLR = 2499;    // reload value
IWDG->KR  = 0xCCCC;  // start watchdog
// Pet:
IWDG->KR  = 0xAAAA;

The timeout formula: t = (RLR + 1) × prescaler / f_LSI. With RLR = 2499, prescaler = 64, and f_LSI = 40 kHz: (2500 × 64) / 40000 = 4.0 s.

The ±20% LSI problem. The LSI oscillator on STM32 is uncalibrated from the factory. The reference manual specifies a nominal frequency (32 kHz on STM32H7, 40 kHz on most others) but the actual frequency can vary ±20% across temperature and silicon. A 4-second nominal timeout can fire anywhere between 3.2 s and 4.8 s. Design your pet interval accordingly — if your main loop runs every 100 ms, a 4-second watchdog gives you 32–48 loop iterations of margin, which is usually sufficient. If you need sub-second precision, calibrate LSI using TIM5 CH4 input capture against the HSE reference, or switch to WWDG (which runs on the much more stable PCLK1).

IWDG vs WWDG

IWDG resets the device if you pet it too late. That is the only error condition it detects: the main loop stopped running entirely.

WWDG (window watchdog) adds an upper bound: it resets the device if you pet it too early or too late. This detects timing violations in addition to deadlocks. The window is configured with the W[6:0] bits in WWDG_CFR. Petting before the counter falls below W triggers an immediate reset — you are running too fast or the pet code is being called from the wrong place in the loop.

Use IWDG for safety-critical recovery from hangs. Add WWDG if you need to verify that real-time deadlines are being met — motor control loops, safety interlocks, or any system where running too fast is also a fault condition.

nRF52 WDT — CRV register and LFCLK

The nRF52 WDT is clocked by LFCLK at 32.768 kHz. The CRV (Counter Reload Value) register is 32-bit, giving a maximum timeout of over 36 hours.

timeout_s = (CRV + 1) / 32768
CRV = ceil(timeout_s × 32768) - 1

Round CRV up rather than down so the actual timeout is never shorter than your target — if the main loop has an 800 ms worst-case cycle time and you configure a 1-second watchdog, you need the hardware to give you the full second, not 999.97 ms.

Reload registers and multi-threaded safety. The nRF52 WDT supports up to eight independent reload registers (RR[0] through RR[7]). You configure which channels are active via the RREN register, and the watchdog only pets successfully when all enabled channels have been written since the last reload. This means you can assign one channel per RTOS task and the watchdog only resets if every task has checked in — a single stuck task triggers a reset, even if every other task is running fine.

NRF_WDT->RREN = 0x03;          // enable channels 0 and 1
NRF_WDT->TASKS_START = 1;
// Task A pets:
NRF_WDT->RR[0] = 0x6E524635;
// Task B pets:
NRF_WDT->RR[1] = 0x6E524635;

In Zephyr, use the WDT driver API rather than direct register access: wdt_install_timeout(), wdt_setup(), and wdt_feed(). Set CONFIG_WDT_NRFX=y and CONFIG_WATCHDOG=y. The driver handles channel allocation and maps each Zephyr channel to an nRF52 RR register.

RP2040 — µs-resolution load register

The RP2040 watchdog uses a 1 MHz clock and a 24-bit load register in microseconds. The pico-sdk watchdog_enable(delay_ms, pause_on_debug) API converts milliseconds to microseconds internally. Maximum timeout is 16.7 seconds (0xFFFFFF µs).

The pause_on_debug parameter stops the watchdog counter when the processor is halted in a debugger, preventing spurious resets during debugging sessions. Set it to true for development, and reconsider for production depending on your safety requirements.

ESP32 Task Watchdog (TWDT)

The ESP32 Task Watchdog monitors FreeRTOS tasks. Unlike the other peripherals covered here, it is not a simple hardware counter — it is a software watchdog built on top of the hardware timer peripheral. Tasks must explicitly subscribe and feed the watchdog via esp_task_wdt_add(NULL) and esp_task_wdt_reset().

The trigger_panic parameter in esp_task_wdt_config_t controls whether a watchdog timeout causes a panic (with backtrace and core dump) or a silent reset. Set this to true in production — the backtrace is the only way to diagnose which task stopped feeding the watchdog.

Petting the watchdog correctly in an RTOS

The most dangerous watchdog anti-pattern: petting the watchdog from a timer ISR or a high-priority interrupt that always runs, regardless of whether the main application is healthy. This defeats the purpose entirely — the watchdog fires correctly but the device appears to the watchdog as healthy while the application is deadlocked.

The correct pattern in an RTOS:

  1. Create a dedicated watchdog task at the lowest useful priority, below all application tasks.
  2. Have application tasks set a flag or increment a counter when they complete a cycle.
  3. The watchdog task checks that all required tasks have checked in, then pets the watchdog.
  4. If any task misses its deadline, the watchdog task does not pet, and the hardware times out.

On nRF52 with multiple reload registers, you can skip the software layer — assign one RR channel per task and let the hardware enforce all-tasks-healthy directly.

Common mistakes

Petting during flash write operations. An STM32 flash erase can take up to 2 seconds (depending on sector size and part). If your watchdog timeout is 1 second, the device resets during erase. Either extend the timeout before flash operations (write a new RLR after unlocking) or pet the watchdog between erase and write operations.

Relying on nominal LSI frequency without margin. A 2-second IWDG timeout configured for an LSI running 20% fast will actually fire at 1.6 seconds. If your main loop worst-case is 1.8 seconds, the watchdog fires spuriously under cold temperature conditions. Add at least 30–40% margin over your worst-case loop time, accounting for the full ±20% LSI range.

Petting in an interrupt that masks the real deadlock. If a high-priority ISR fires on a regular timer and you pet the watchdog there, a deadlock in the main thread will never trigger the watchdog reset. The interrupt keeps running, the watchdog keeps getting petted, and the device appears healthy while the application has been stuck for hours.

Forgetting to start the watchdog in debug builds. Developers often disable the watchdog in debug builds to avoid resets during breakpoints. This is reasonable during active development, but it means the watchdog code path is never tested. Run at least some integration tests with the watchdog enabled to verify your pet logic actually works.

Not handling the watchdog reset flag. On reset, check RCC->CSR (STM32) or NRF_POWER->RESETREAS (nRF52) to detect whether the last reset was caused by the watchdog. Log this, send it to your telemetry system, and increment a counter in non-volatile storage. A device that watchdog-resets in the field needs investigation — it is not a normal operating mode.

Frequently asked questions

Why does my STM32 watchdog fire at the wrong time? +

The STM32 IWDG runs on the internal LSI oscillator which has a ±20% tolerance. A 2-second nominal timeout can fire anywhere between 1.6 s and 2.4 s depending on temperature and silicon variation. For tight timing requirements, calibrate LSI against HSE using TIM5 input capture (available on F4/F7) or use the WWDG (window watchdog) which runs on PCLK1 — much more accurate but requires more careful programming.

What is the difference between IWDG and WWDG on STM32? +

IWDG (independent watchdog) runs on LSI, is fully independent of the main clock, and resets if you pet it too late. WWDG (window watchdog) runs on PCLK1, and resets if you pet it either too early OR too late — the window is configurable. IWDG is for catching deadlocks and infinite loops. WWDG is for catching timing violations in real-time systems. Most designs use IWDG; WWDG is for safety-critical timing.

How do I safely pet the watchdog in a Zephyr RTOS application on nRF52? +

Use the Zephyr watchdog driver API: wdt_install_timeout(), wdt_setup(), and wdt_feed(). In Zephyr, you register separate channels and feed each one from the appropriate thread or ISR. Do not use NRF_WDT->RR[0] directly — the Zephyr WDT driver may use different channels. CONFIG_WATCHDOG=y and wdt_setup() with WDT_OPT_PAUSE_IN_SLEEP will pause the watchdog during sleep, which is usually what you want for nRF52 BLE devices.

Should I disable the watchdog during firmware updates (OTA)? +

No — the watchdog is especially important during OTA updates, which are a common source of bricking. Instead, increase the watchdog timeout for the duration of the update. On STM32, you can write to IWDG->RLR at any time after unlock to change the reload value. Set a longer timeout (e.g. 30 s) before erasing each flash page, then pet immediately after. After the update, the device reboots and re-initialises with the normal shorter timeout.

Newsletter

The embedded engineer's weekly cheat sheet

Register tricks, timing gotchas, and tool updates. One email per week. No fluff.

No spam. Unsubscribe anytime.