Leonardo: How to fix boot_loop after WDT

Hi all
this topic is not new, but I still didnt find any solution. please correct me if I wrong

I have Micro board with last bootloader from IDE 1.8.9
and if I put in the code wdt reboot (doesnt matter what the condition of it)

wdt_enable(0);

the micro start works not stable:
-sometimes (70%) COMx is not displayed as port and Serial monitor couldnot connect to Micro
-sometimes (30%) goes to infinite loop

and as I understand there are no optiboot like for nano (where issue is resolved - Serial monitor always connecting...)

In the 2nd thread you gave a link to, forum member pjanco pointed out the problem with using watchdog on Leonardo is not in the bootloader. It is in the core. You can edit the core to remove or comment out the offending code. The core is in the Arduino app installation. On my computer it is in the hardware/arduino/avr/cores/arduino subdirectory, and the file he is talking about is CDC.cpp. This is the section of code that deals with Serial communication on the Leonardo.

You can think of the core as parts of code that run on your Leonardo in addition to your sketch. The serial communication part of the core runs in the background on the Leonardo. The part if its job that uses watchdog is the part that watches for the 1200 baud touch, which is the signal from the Arduino IDE indicating it is time to restart the MCU and accept a new sketch upload via the bootloader. Even if you don’t have a bootloader (such as you upload your sketch using a programmer), that piece of code would still run on your Leonardo.

So, in the CDC.cpp in your Arduino IDE, you can edit it to comment out the 1200 baud touch code. I just did it on my Arduino IDE and it worked fine. I used /* to begin the comment, and */ to end the comment, and using that method I commented out the whole section of code. Here is the section I commented out in the IDE version 1.8.9:

/*
			// We check DTR state to determine if host port is open (bit 0 of lineState).
			if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0)
			{
#if MAGIC_KEY_POS != (RAMEND-1)
				// Backup ram value if its not a newer bootloader and it hasn't already been saved.
				// This should avoid memory corruption at least a bit, not fully
				if (magic_key_pos != (RAMEND-1) && *(uint16_t *)magic_key_pos != MAGIC_KEY) {
					*(uint16_t *)(RAMEND-1) = *(uint16_t *)magic_key_pos;
				}
#endif
				// Store boot key
				*(uint16_t *)magic_key_pos = MAGIC_KEY;
				// Save the watchdog state in case the reset is aborted.
				wdtcsr_save = WDTCSR;
				wdt_enable(WDTO_120MS);
			}
			else if (*(uint16_t *)magic_key_pos == MAGIC_KEY)
			{
				// Most OSs do some intermediate steps when configuring ports and DTR can
				// twiggle more than once before stabilizing.
				// To avoid spurious resets we set the watchdog to 120ms and eventually
				// cancel if DTR goes back high.
				// Cancellation is only done if an auto-reset was started, which is
				// indicated by the magic key having been set.

				wdt_reset();
				// Restore the watchdog state in case the sketch was using it.
				WDTCSR |= (1<<WDCE) | (1<<WDE);
				WDTCSR = wdtcsr_save;
#if MAGIC_KEY_POS != (RAMEND-1)
				// Restore backed up (old bootloader) magic key data
				if (magic_key_pos != (RAMEND-1)) {
					*(uint16_t *)magic_key_pos = *(uint16_t *)(RAMEND-1);
				} else
#endif
				{
				// Clean up RAMEND key
					*(uint16_t *)magic_key_pos = 0x0000;
				}
			}
*/

Ok, now what happens when you comment that out? Well, after you upload the first sketch onto the Leonardo after you have commented out the 1200 baud touch code, the Leonardo will no longer auto reset to accept new sketches. You will need to tap the reset button manually on the Leonardo during sketch compilation, so it will be running the bootloader when it reaches the upload step. If you use your Arduino IDE to write other sketches for Leonardo that don’t have a watchdog, they will also be affected. Auto reset for upload will be disabled. I like to use the portable IDE option, so I can have a completely separate IDE, installed separately, for when I do weird stuff like this. It is also possible for you to make a custom core if you like, so you can have one that does not have the 1200 baud touch auto reset feature. I don’t know how to do that, but I’m sure you could research it online.

Here is my test sketch, this takes too long to run, so the watchdog catches that and restarts my Leonardo. Before I patched the CDC.cpp file to comment out the 1200 baud touch auto reset, if I opened serial monitor, the sketch would run endlessly and the watchdog did not restart the Leonardo.

#include <avr/wdt.h>

void setup() {
  pinMode(13, OUTPUT);
  Serial.begin(115200);
  wdt_enable(WDTO_4S);
}

void loop() {
  wdt_reset();
  digitalWrite(13, 1);
  delay(1000);
  for (int i = 0; i < 11; i++) {
    digitalWrite(13, !digitalRead(13));
    Serial.println(i);
    delay(500);
  }
}

So now with patched CDC, and opened serial monitor, your test sketch works properly ?

  • it restarts every 4S?
  • serial monitor continue printing after restart ?

alexblade:

  • it restarts every 4S?

Yes

alexblade:

  • serial monitor continue printing after restart ?

No

If the Leonardo restarts, it loses connection via serial monitor. I need to quit and restart the serial monitor in order to see more output from the Leonardo serial.

If I don't like that, I would use an FDTI or bluetooth or some other serial adapter that is not being power cycled or rebooted along with the Leonardo. Then it would stay connected to serial monitor. I would connect to the RX and TX pins on the Leonardo, which is Serial1.

got you! thnx