NetBurner 3.5.8
PDF Version
Watchdog

Example Path: examples/PlatformSpecific/MODRT1171/Watchdog

Supported Platforms: MODRT1171

Watchdog (MODRT1171)

Overview

This example shows how to use the hardware watchdog on the MODRT1171 module (i.MX RT1171) to automatically recover a hung application by rebooting it. A watchdog is a hardware timer that resets the processor unless the application keeps restarting it ("servicing" it). If the application locks up and stops servicing the watchdog, the timer expires and the module reboots itself back into a working state.

The example is driven by a simple serial menu on the debug console, and on every boot it reports why the module last reset.

Arming and servicing the watchdog is done through a small helper API in src/nbwatchdog.h:

WatchdogEnable(4000); // reboot the module if not serviced within ~4 seconds
...
WatchdogService(); // call this comfortably more often than the timeout

That is the whole idea: arm it once, then call WatchdogService() regularly from healthy code. Stop servicing it (because you crashed or hung) and the module reboots on its own.

Note
The i.MX RT1171 contains several watchdog blocks: WDOG1 and WDOG2 (the general-purpose i.MX watchdogs), RTWDOG3 in the CM7 domain and RTWDOG4 in the CM4/low-power domain. System startup disables all of them each boot, and this example uses WDOG1, the general-purpose application watchdog. See Why WDOG1 at the end.

Quick start – the serial menu

Connect a terminal to the debug serial port. The menu:

Key Action
R Show why the module last reset
E Arm the watchdog (prompts for a timeout in seconds)
F Service the watchdog once
A Toggle automatic servicing on/off
X Stop servicing -> demonstrate the automatic reboot
B ForceReboot() – a plain software reboot, for comparison
? Redisplay the menu

A typical session:

  1. Press E and accept the 4 s default. The watchdog is now armed, and a background task services it automatically, so the module keeps running.
  2. Press X. Servicing stops; a few seconds later the module reboots on its own. That reboot – timed to the moment you stopped servicing – is the watchdog doing its job.
  3. Press R after the reboot: the cause reads Raw WDOG1 hardware timeout – the watchdog is the one reset source on this module that positively identifies itself. Press B to trigger a plain software reboot and compare.

Using WDOG1 in your own application

The API is just four calls (all in src/nbwatchdog.h):

void WatchdogEnable(uint32_t timeoutMs); // arm the watchdog
void WatchdogService(); // service (restart) it
bool WatchdogIsEnabled(); // is it armed?
uint32_t WatchdogTimeoutMs(); // the timeout currently set

Usage is: arm once with a timeout, then service it from healthy code more often than that timeout.

A few rules worth knowing:

  • Timeout range is 1 to 128 seconds (values are clamped to that range and resolve in 0.5 s steps).
  • Once armed, the watchdog cannot be turned off – only a reset clears it. This is by hardware design: it stops buggy code from silently disabling its own safety net. Choose the timeout accordingly.
  • Service from a dedicated task, not from a loop that can block. If the code that services the watchdog can get stuck waiting on something, it will stop servicing and reboot the module by accident. This example services WDOG1 from a small dedicated task – see below.
  • Firmware updates are handled for you. Arming the watchdog also makes reprogramming safe automatically – see Servicing during firmware updates.

How the automatic reboot works

WatchdogEnable() arms WDOG1, and an expired timeout performs a full hardware reset of the i.MX RT1171. Verified on this hardware, the module reboots cleanly from that reset, straight back into the application:

not serviced in time -> hardware reset -> automatic reboot back into the application.

The watchdog reset also resets the WDOG block itself, so the module always boots un-armed – an application that arms the watchdog can never trap itself in a reset loop faster than its own startup.

Because the reset happens entirely in hardware, it works no matter how badly the software is wedged: a hung task, a spinning interrupt handler, or a hard fault with interrupts masked all end the same way, with the watchdog resetting the module.

Service from a dedicated task, not an input loop

This example services WDOG1 from its own small task (WatchdogServiceTask in src/main.cpp), not from the menu loop. That is deliberate. The menu loop blocks on gets() waiting for a keypress; if the servicing lived in that loop, an idle console (nobody typing) would stop the servicing and reboot the module. A separate service task keeps the watchdog serviced no matter what the rest of the application is doing. The menu's X command simply tells that task to stop, which is how the demonstration reboot is triggered.

In a real application you would go one step further and make the service task service the watchdog only while your critical work is making progress (for example, only if a "heartbeat" counter bumped by that work keeps changing) – so that a hang in the work itself still trips the watchdog.

Servicing during firmware updates (automatic)

Reprogramming the module writes the new application to flash, and a flash write stalls normal task scheduling – long enough that an armed watchdog would otherwise reset the module in the middle of the update. If that happened, and the application re-armed the watchdog on boot, updates could become impossible to complete and the application unrecoverable (short of the recovery-jumper procedure).

There is no good reason to arm the watchdog but leave updates able to trip it, so WatchdogEnable() takes care of it automatically: it registers the NetBurner watchdog service hook (watchdog_service_function), which the flash/update routines call throughout an update. Nothing extra is required on your part – an armed watchdog simply survives a firmware update.

What a watchdog reboot affects

A watchdog reboot resets the i.MX RT1171 internally; it does not drive a reset out to devices on your carrier board. On-module peripherals come back because the boot firmware re-initializes them as the module starts up. If your carrier board has devices that must be reset in lock-step with the module, reset them from your application at startup, or wire them to the module's reset circuitry per the MODRT1171 hardware documentation.

Reading why the module last reset

On every boot the example decodes the processor's System Reset Status Register (SRC->SRSR) and prints a human-readable cause (menu key R). The i.MX RT1171 reset controller keeps per-core status, so the example can distinguish power-on/reset-pin, a CM7 software reset, a raw watchdog timeout, RTWDOG3/RTWDOG4, the code watchdog (CDOG), a CM4-initiated reset, JTAG, temperature and over-voltage resets. The example clears SRC->SRSR each boot, so each boot reports exactly the reset that caused it rather than an accumulation of history.

Two details worth knowing, both verified on hardware:

  • Power-on and the external reset pin are one category. Both arrive at the processor as POR_B and set the same status bit, so they cannot be told apart.
  • WDOG1->WRSR is shown raw but not decoded. It records the last reset of the WDOG block itself (power-on or watchdog timeout) and keeps that stale value across software resets, which do not reset the block – so on any given boot it may describe a much older reset than the one that just happened.
Note
A watchdog reset is positively identified. The remaining ambiguity is between ForceReboot() and a reprogram: both end in the same CM7 reset request, so those two present identically as software reset.

Expected serial output

After a ForceReboot() or a reprogram:

Application: MODRT1171 Watchdog
NNDK Revision: <release>
Target: MODRT1171 (i.MX RT1171)
Last reset cause (SRC->SRSR = 0x08000002, WDOG1->WRSR = 0x0010)
Software reset (CM7 reset request / lockup)
(a ForceReboot and a reprogram both look like this)
========== MODRT1171 Watchdog Menu ==========
Status: WDOG1 off | Auto-service: ON
...
void ForceReboot(bool fromIRQ=false)
Initiates an immediate hardware-level system reset of the NetBurner device.

After a power cycle:

Last reset cause (SRC->SRSR = 0x00010001, WDOG1->WRSR = 0x0010)
Power-on / external reset pin (POR_B)

After a watchdog reset:

Last reset cause (SRC->SRSR = 0x00200020, WDOG1->WRSR = 0x0002)
Raw WDOG1 hardware timeout

(SRSR reports each source twice – once per core – which is why the values above pair a low bit with its high-half twin.)

After arming and pressing X:

Stopping the service. Within about 4000 ms the watchdog's hardware
reset will fire. ...
waiting for watchdog reset... 15
<module hardware-resets and reboots on its own>

Recovery (if you ever wedge a board)

Because the watchdog cannot be turned off once armed, application code that arms it at boot and then hangs before servicing it can create a boot loop. This example avoids that by staying un-armed at boot – so arming it here can never brick the board. If your own code does get a board stuck, use the MODRT1171 recovery procedure to load a known-good application: see MODRT1171.

Why WDOG1

WDOG1 is the general-purpose application watchdog on the i.MX RT1171 and is all a NetBurner application needs. Of the other watchdog blocks, WDOG2 is a second instance of the same peripheral, RTWDOG3 is a low-power watchdog in the CM7 domain, and RTWDOG4 belongs to the CM4/low-power domain and has no CM7 interrupt vector. System startup disables all of them on every boot, so an application watchdog must be armed explicitly – which is exactly what WatchdogEnable() does with WDOG1.

Further reading

  • src/nbwatchdog.h / src/nbwatchdog.cpp – the watchdog helper API.
  • arch/cortex-m7/cpu/MIMXRT11xx/include/MIMXRT1176_cm7.h – WDOG and SRC register and bit-field definitions.
  • arch/cortex-m7/cpu/MIMXRT11xx/source/cpu_hal.cppDoSWReset(), the software-reset path behind ForceReboot().
  • docs/root/NXP/IMXRT1170RM.pdf – reference-manual chapters "WDOG" and "SRC" (System Reset Controller / SRSR).