How do you use a watchdog timer to recover a wedged device without hiding the bug that wedged it?
Watchdog recovery in firmware only works if the code that kicks the watchdog can detect task progress. Kick from one supervisor after checking heartbeats, record reset cause and diagnostics in retained memory, and treat watchdog resets as defects to investigate.
What the interviewer is scoring
- Does the candidate insist the kick be conditional on evidence of progress
- Whether the answer names a kick site that keeps running while the real work is stuck
- That they preserve the reset cause and forensic state across the reset itself
- Whether physical outputs and external state after a reset are considered, not only the CPU
- Whether a rising watchdog-reset count is treated as an alarm rather than as resilience
Answer
Short answer
Have one supervisor kick the watchdog only after every critical task proves progress, preserve reset diagnostics, and use the reboot to recover while still fixing the underlying hang.
Mention reliability where it changes the risk, the owner, or the next check. A useful reliability point should make the answer more testable, not merely longer. Tie reliability back to the scenario so the interviewer can see why it matters here.
A watchdog is a bet that one specific thing cannot fail
A hardware watchdog is a counter clocked independently of the CPU, usually from its own low-speed oscillator, that resets the part if firmware does not refresh it within a timeout. Its value comes entirely from that independence: it keeps counting through a spin loop, a corrupted stack, a deadlock, a wild jump into flash, and a PLL that lost lock.
So the design question is never "do we have a watchdog". It is: which code refreshes it, and is that code capable of running correctly while the device is nonetheless useless? Every failure of a watchdog design in the field is a failure to answer the second half.
Consider a device whose job is to sample a sensor at 100Hz and publish over a radio. The radio task deadlocks on a mutex. The 1kHz system tick keeps firing, the idle task keeps running, and the CPU is perfectly healthy. If the watchdog is refreshed by anything on that healthy path, the device sits there indefinitely publishing nothing, and the watchdog you paid for reports that everything is fine.
Kicking from a timer interrupt is the same as disabling it
This is the specific mistake to name, because it is extremely common and it is usually introduced as a fix. Somebody sees spurious resets during a long flash erase, moves the refresh into the periodic timer ISR so it can never be starved, and the resets stop. Both statements are true and the second is the problem: the resets stopped because the watchdog no longer observes anything except whether interrupts are still being serviced.
An ISR is nearly the worst possible kick site. It preempts application code, so it keeps running while the application is deadlocked, live-locked, stuck in an unbounded loop, or corrupt. It converts a watchdog into a check that the interrupt controller works.
The correct structure is one kick site in the main loop or in a dedicated low-priority supervisor task, which refreshes the watchdog only after confirming that every task it supervises has made progress since the last check. Each task sets its own bit on completing a unit of real work — not on entering its loop, which every stuck task also does — and the supervisor clears the set once satisfied.
/* One bit per supervised task. Each task sets its bit after finishing
a real unit of work, never on merely being scheduled. */
#define TASK_SENSOR (1u << 0)
#define TASK_RADIO (1u << 1)
#define TASK_CONTROL (1u << 2)
#define ALL_TASKS (TASK_SENSOR | TASK_RADIO | TASK_CONTROL)
static volatile uint32_t checked_in;
void task_checkin(uint32_t bit) { checked_in |= bit; } /* single-bit set */
void supervisor_step(void) {
if ((checked_in & ALL_TASKS) == ALL_TASKS) {
checked_in = 0;
watchdog_refresh(); /* the only call site in the firmware */
}
/* Otherwise: do nothing. Doing nothing is the mechanism. */
}
The supervisor's own period and the watchdog timeout must then be chosen from the slowest supervised task's deadline. If the sensor task legitimately runs once every two seconds, a one-second timeout resets a working device, and the pressure to "fix" that by loosening the check-in is where designs quietly rot back into unconditional kicks.
Making the reset informative rather than invisible
A watchdog reset that leaves no trace is a bug deleting its own evidence. On restart, firmware must read the reset-cause status the hardware provides and branch on it, because a power-on reset, an external pin reset, a brownout and a watchdog reset each mean something different about what just happened.
Beyond the cause, you want the forensics. Most toolchains let you place variables in a section that the start-up code does not clear — conventionally .noinit — so a small crash record survives a reset that does not cut power. Write the check-in bitmask at the moment the supervisor gave up, the last task to run, a fault-status register value, a wrapping log of the last few state transitions, and a reset counter. Then on the next boot, publish it.
flowchart TD
A[Reset] --> B{Reset cause}
B -->|Power-on| C[Clear noinit record]
B -->|Watchdog| D[Read surviving record]
B -->|Brownout| E[Log supply event]
D --> F[Increment reset counter]
F --> G{Counter over threshold}
G -->|No| H[Normal boot and report record]
G -->|Yes| I[Enter safe mode<br/>no auto-restart]The interesting branch is the bottom one rather than the logging. A device that reboots and resumes forever is indistinguishable from a healthy device in most telemetry, so the escalation path matters: after a few watchdog resets in a short window, stop retrying the same thing. Boot into a degraded mode that keeps the radio and the diagnostics alive and leaves the failing subsystem off, so the fault can be read out instead of being cycled through repeatedly.
The reset does not reset the world
The CPU restarting is only part of recovery, and this is where an embedded answer separates from a server one. A heater relay energised before the hang is still energised through the reset. A motor driver holding a duty cycle keeps holding it until something reprogrammes it. A GPIO configured as an output returns to its reset state, which may be a floating input that lets an external pull resistor decide the actuator's position. A device on a shared bus may still hold the line low, wedging every other node.
So the boot path has to drive outputs to a defined safe state before it does anything else, and the hardware has to be designed so that "the MCU is not running" is itself safe: pull resistors chosen deliberately, drivers with their own enable that fails off, external supervisors on anything genuinely dangerous. Peripherals with independent state, such as an external radio or a bus expander, often need an explicit hard reset during boot, because they did not restart when the MCU did and may still be part-way through a transaction.
Two further details signal experience. First, the watchdog should be enabled as early in boot as is practical, ideally by hardware configuration rather than by a firmware register write, so a hang during initialisation is also covered — the alternative leaves a window where a wedged bring-up loop runs forever. Second, a long blocking operation such as a flash erase during a firmware update needs the timeout planned around it rather than the kick relocated into it: either the timeout accommodates the longest erase, or the erase is chunked so the supervisor still runs between chunks.
Treat every watchdog reset as a defect with a stack of evidence attached. The moment the count becomes a metric someone tolerates rather than an alarm someone investigates, the watchdog has stopped being a safety net and become a way of not finding out.
© 2026 Preptima. Originally published at preptima.com.
Likely follow-ups
- Two tasks run at 1Hz and 100Hz. How do you build a single check-in scheme that catches either one stalling without the fast task masking the slow one?
- How would you distinguish a genuine firmware hang from a brownout that also resets the part?
- What is a windowed watchdog protecting against that a conventional one does not catch?
- Your device reboots every ninety seconds in the field but never on the bench. What do you instrument first?
Related questions
- How do you size the stack and the heap on a device with a fixed RAM budget?mediumAlso on firmware5 min
- How do you isolate a degraded dependency and halt a cascading failure before thread pool exhaustion takes down the entire microservice ecosystem?hardAlso on reliability2 min
- How do you conduct a post-mortem after a catastrophic Sev1 outage triggered by a junior engineer's mistake, without succumbing to the blame game?hardAlso on reliability2 min
- You want to prove the system survives losing a database, in production, on a Tuesday afternoon. How do you run that without being fired?hardAlso on reliability7 min