ATMEGA328 locks up on watchdog reset

I am trying to use a watchdog timer to reset an ATMEGA328P if the software gets stuck for more than 4 seconds. Something does happen after four seconds... the ATMEGA is bricked until the next power cycle.

Here is the minimal code that demonstrates the problem, with the wdt_reset uncommented, it outputs "running" every second: with it commented, it outputs "running" four times, then stops... it is impossible to download a new sketch (via serial port) until the power is cycled.

#include <avr/wdt.h>

void setup() {
  Serial.begin (9600);
  Serial.println ("Reset");

  wdt_enable(WDTO_4S);
}


void loop() {
//   wdt_reset ();

  delay (1000);
  Serial.println ("running");
}

If you want to use the WDT then you have to reset it all the time. If you stop resetting then it will block everything after the watchdog period elapsed.

@DrDiettrich Yes, I know that. This is a test program to demonstrate what happens when a watchdog timeout occurs, so I have deliberately commented out the wdt_reset.

What I want to happen is that the ATMEGA resets when a watchdog timeout occurs. What actually happens is that it is bricked.

Try adding this at the beginning of setup():
wdt_reset ();

If you are using a bootloader, use optiboot.

@6v6gt thanks for the suggestion, but adding wdt_reset() at the beginning of setup didn't make any difference.

Is it possible that the regular arduino bootloader is taking more than 4 seconds?

Optiboot is the bootloader used on the Uno. It handles the watchdog timer correctly. The Nano bootloader does not. Which, if any, have you installed?
If none, then move the two serial statements to the end of setup().
The 4 seconds does not apply after a reset. I think it drops to 16ms and the watchdog survives the reset.

1 Like

The WDT causes a reset unless it's configured for interrupt mode. See Table 11-1 Watchdog Timer Configuration.

Eventually your bootloader checks for the reason of the reset, finds the WDT and bricks.

@6v6gt Thanks: Resetting the WDT to 16ms explains my problem. I use an 8MHz version of the standard bootloader on a custom board. I had a quick look at optiboot and I will probably need to make my own version of it: that needs more investigation.

The explanation is here:

My recollection is the original IDE bootloader did not allow the WDT to function. It seems the default WDT time would time out before the bootloader finished its thing.
To use the WDT I had to install the optiboot bootloader. It now works fine with my AT323P

1 Like

Eventually your bootloader checks for the reason of the reset, finds the WDT and bricks.

@DrDiettrich It that's true, it's about as helpfui as chaining the parachutes to an aircraft.

It's up to you to specify the appropriate action after a watchdog interrupt. If you don't specify that parachutes should be used...

Do you really need a bootloader? With an ICSP header on the board you can, via a programmer, load a sketch without one.

@6v6gt I ran a quick test without the bootloader and that definitely solves the problem.

I do need a bootloader for my custom boards, because I have an nrf24L01 hard wired to the SPI port: without a bootloader, field upgrades would be impossible.

Thanks for your help.

Be aware that there are two major versions of Optiboot out there. There is the version included with the Arduino IDE (and used on the Uno), which resets the WDT early in the boot cycles, and thus does not have the "bricking" problem.

There is also the latest development version (most easily obtained in .hex form via The MCUDude Cores, which also solves the bricking problem, but has some other new features, like passing the "reset cause" to the application.

My recollection also.

Often used to get Pro Minis affected by that 'bug'.

I replaced the bootloaders with the one from Minicore.

Does anyone know a method of identifying which boot loader is installed in a AT328P? Perhaps a register that could be read by a purpose written code.

Well, there is GitHub - WestfW/fusebytes: Arduino sketch for printing info about chip signature, fuses, bootloader version, etc
It might be a bit rusty.

[Edit] More details: one of the first things I did when I took over maintenance of the Optiboot bootloader was to add an actual version number to the binary, is a spot that is easily readable. And I started updating it. Unfortunately, this doesn't identify bootloaders from before that change. Also, the version number isn't readable by sketches, with the normal Arduino "protection bits." (I tried at one point to get the protection bits changed, but that idea was not met with much enthusiasm ("reduce protection? Inconceivable!"))

The version number IS reported during upload of a sketch, if you have the "Verbose upload" preference selected:

     Programmer Type : Arduino
     Description     : Arduino
     Hardware Version: 3
     Firmware Version: 4.4
     Vtarget         : 0.3 V
     Varef           : 0.3 V
     Oscillator      : 28.800 kHz
     SCK period      : 3.3 us

Pre-optiboot bootloaders will report Hardware Version 2 (I think), and typically Firmware version 1.16 (sorry, I'm not finding a board that I haven't upgraded to optiboot...) (There are versions of the old bootloader that fixed the WDT problems as well. IIRC, both Adafruit and Sparkfun were using a fixed bootloader in their "more official" Arduino-compatible boards, prior to Optiboot. Unfortunately few vendors of the Nano or Nano clones (or the "pro mini" clones) picked up the fixed version.) (and AFAICT, no one updated the version number, for fear of incompatibility with PC-side tools, or something.)

Early versions of optiboot (Post Uno, but pre IDE 1.0) will show Firmware 3.3. I think the WDT fix went in in 4.1

Current Arduino bootloader is firmware 4.4

Latest development Optiboot is 8.2 (that's not really as bad as it looks; most of the changes that have been made are not relevant to the common ATmega328 boards, and many are build environment improvements.)

1 Like

@JohnRob Optiboot writes its version number at the top of memory.: the standard bootloader leaves it as FF.

Serial.println (pgm_read_byte(0x7FFF), HEX);

This prints out 8 for Optiboot and FF for the regular bootloader.

Alas, the standard lock bit settings make the bootloader section unreadable from sketches. :frowning: