Atmega328p locks up on watchdog reboots

I made a nano-like board with an atmega 328p as shown in the schematic

My plan is to run it without bootloader so it can boot faster (without the waiting period). But when I upload the following code to it without the bootloader, after 4 seconds, it locks up until I unplug and replug it. When I use this code with the bootloader, the watchdog works fine. I tried the same code on a third party nano (with an atmega328p in it, with and without the bootloader), it works fine. So did I do anything wrong when I draw the circuit?

#include <avr/wdt.h>
#include <Wire.h>

// the setup routine runs once when you press reset:
void setup() {
  wdt_disable(); //disable wdt at the first of code to prevent it always reboot


  delay(50); //this latency is waiting for the analog parts to ramp up.
  wdt_enable(WDTO_4S); //

// the loop routine runs over and over again forever:
void loop() {
  // read the input on analog pin 0:
  int sensorValue = analogRead(A0);
  // print out the value you read:
  //  wdt_reset(); //
  delay(100);        // delay in between reads for stability

Why have you commented this out ?

To have the watchdog trigger the chip reboot 4 seconds after power on.

From system start, you have ~16ms to react to prevent the watchdog retriggering after being triggered:

init() runs before setup() but I can't imagine it takes so long.

Okay. Does it mean I made wrong fuse setting?
Note I did the same thing to a third party nano, and it works just fine. I checked the datasheet of the 328p, and didn't find any specific fuse for the watchdog.

The fuse is here WDTON (see watch dog timer always on) : AVR Fuse Calculator for ATmega328P

Depending on the voltage Vcc, it could also be a brown out problem that is causing the continuous reset (also a fuse setting)

I think the Nano has a external pullup resistor on its reset pin. Your board seems to have the reset pin floating.

The problem doesn't fix with a fuses.

It is necessary to reset the watchdog as soon as possible, even before the setup() starts. Paste the following code at the beginning of the sketch

#include <stdint.h>
#include <avr/wdt.h>
uint8_t mcusr_mirror __attribute__ ((section (".noinit")));
void get_mcusr(void) \
  __attribute__((naked)) \
void get_mcusr(void)
  mcusr_mirror = MCUSR;
  MCUSR = 0;

You can read about it in the av-libc documentation:

Thanks a lot b707! I will try this out later. I wonder why this didn't happen when I load this code to the nano board (with and without the bootloader).

In the case of the bootloader, this is understandable. Some arduino bootloaders already contains these lines in its code, so it does not have such problems.

Nah; the beginning of setup() will be fine, and setting MCUSR is not needed (I mean, it's a good idea, because those bits are sticky across resets, but...)
16ms (the minimum watchdog time) is a LONG time compared to the pre-setup initialization code.

I had the reset pin pulled up (not shown in the schematic)

this doesn't work. But after I tried almost every combination of the fuse settings, and when I removed the delay(50); in my original code, it works.

I still don't understand why...

Original code:

Ah yes. 50ms delay is longer than the 15ms the default watch dog timer delay gives you in a retrigger situation.
Remember. You were told :


Is it clear now ?

I did disable the watchdog right after it entered setup:

wdt_disable(); //disable wdt at the first of code to prevent it always reboot

Doesn't that prevent watchdog from rebooting the mcu?

Sorry. Yes you did. The line spacing must have confused me. If you are still experimenting you could also try, as the first statement, setting MCUSR to zero or wdt_enable(WDTO_4S) just to give it more time to carry out the later disable.

1 Like

I did disable the watchdog right after it entered setup

After delay(50) is NOT "right after entering setup." Is is half-a-seconds later.
It doesn't prevent the WDT from resetting the microcontroller sometime during that 50ms. As others have said, the INTERVAL for the WDT resets to 16ms when the chip is reset (I consider that relatively undesirable behavior. But the alternative where some registers are not reset completely is also bad.)

(It might be worth pointing out that the newer AVRs, like the ATmega4809 used on Nano Every, have a fuse that sets the WDT period at reset, instead of just resetting it to zero. It can do this because they've expanded from 3 fuses to 11 fuses!)

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.