arduino / ArduinoCore-avr

The Official Arduino AVR core
https://www.arduino.cc
1.24k stars 1.05k forks source link

ProMini: Reboot loop when using watchdog #150

Open tuxedo0801 opened 8 years ago

tuxedo0801 commented 8 years ago

Hi there,

i have the following problem:

I have an arduino sketch which accept some configuration-details over the serial connection. After applying some configuration, a "reboot" is required. On my leonardo and micro boards, this works quite well by using the watchdog to reset the board:

    wdt_enable( WDTO_1S ); 
    while(1) {}

But with an arduino pro mini at 3,3V/8Mhz the board loops in a restart-loop, forever. It seems that this issue is already known on the net:

https://andreasrohner.at/posts/Electronics/How-to-make-the-Watchdog-Timer-work-on-an-Arduino-Pro-Mini-by-replacing-the-bootloader/

I know that there are othr techniques to "reboot" an arduino, but the WDT seems to be the only real hardware reboot, triggered by software.

Of course I can use the optiboot bootloader to overcome this issue. But this adds some additional complexity and arduino ide tweaking-skills, which I would like to avoid (there are other people using my sketches/libraries which won't be able to tweak the arduino ide properly).

Would it be possible to fix this in arduino ide direclty? For example by switching to optiboot by default or fix the "bug" in the current used bootloader?!

br, Alex

tuxedo0801 commented 8 years ago

I now tried the optiboot bootloader (with Arduino Nano, instead of ProMini, but the AVR is the same...)... Without any success ... Flashing the bootloader was not a problem, but the issue is not gone...

Any hints on this?

tuxedo0801 commented 8 years ago

A collegue found of, that if he adds the following

##############################################################
## Optiboot on 32pin (SMT) CPUs (Nano, Pro Micro, etc.)
##############################################################

optiboot32.name=Optiboot on 32-pin cpus (3.3V Pro Mini)
optiboot32.upload.tool=arduino:avrdude
optiboot32.upload.protocol=arduino
optiboot32.bootloader.tool=arduino:avrdude
optiboot32.bootloader.low_fuses=0xF7
optiboot32.bootloader.unlock_bits=0x2F
optiboot32.bootloader.lock_bits=0x0F
optiboot32.build.f_cpu=8000000L
optiboot32.bootloader.low_fuses=0xE2
optiboot32.upload.speed=57600
optiboot32.build.board=AVR_UNO
optiboot32.build.core=arduino:arduino
optiboot32.build.variant=arduino:eightanaloginputs
optiboot32.upload.maximum_size=32256
optiboot32.upload.maximum_data_size=2048
optiboot32.bootloader.high_fuses=0xDE
optiboot32.bootloader.extended_fuses=0x05
optiboot32.bootloader.file=optiboot/optiboot_atmega328.hex
optiboot32.build.mcu=atmega328p

to the boards.txt and chose this new board-type in the IDE, the WDT Problem is gone.

So, just replacing the bootloader.file line with the optiboot variant as suggested in the link from my 1st post, seems not enough.

Could someone with more expertise comment on this issue? Is there a way to fix this for all others too? Or does everyone facing this issue has to modify boards.txt themselves?

matthijskooijman commented 8 years ago

Comparing that with the original nano entry, I suspect that the fuse bits influence this. Comparing these, I've found that the clock selection is different (the nano uses the external crystal, your entry uses the internal oscillator) and the bootloader size is different (nano has 1024 words, your entry 256).

I considered the latter is the reason it doesn't work - the bootloader size defines the start address, so when that is still at 1024, the CPU boots up at the wrong place. Since unused bytes are 0xff which I think are just (effectively) nop instructions, the CPU first has to grind through (1024-256=768) 0xff bytes before reaching the bootloader, which is probably some 1600 cycles or something, or 100us. Since the smallest watchdog timeout is 2ms, optiboot should still be in time to reset MCUSR, so perhaps that's not it. Perhaps you could try modifying the nano entry to use optiboot and use high_fuses=0xDE to just set the bootloader size, to see if that is sufficient?

tuxedo0801 commented 8 years ago

That's what I planned to try this evening. I will report back if it works.

If this fixes the problem, the question still is: why does the WDT bring the nano and promini (with default bootloader) etc. in an forever-boot-loop? Can this be fixed in default bootloader?

matthijskooijman commented 8 years ago

The problem is, I think, that the bootloader does not clear the MCUSR register (or specifically the watchdog-related bit in there). This bit is set on a watchdog reset and forces the watchdog enabled. (with a 2ms timeout). The idea is, I think, that an application reconfigures the bootloader on startup, but if it fails to do so, the bootloader is already enabled to prevent a lockup. But this scheme doesn't play well with Arduino's bootloader / sketch separation, so bootloaders should just disable this bit on start, which I think optiboot does but not some of the other bootloaders. It should be fixable, but it's probably better to just switch all boards to optiboot (@cmaglie any thoughts on that?)

tuxedo0801 commented 8 years ago

Sounds good. Of course I can for now switch all to optiboot. But this would be a workaround for a bug (?). So it would be better to fix the bug. As there are many avr 328p boards out there, it would take a while ;-) to get new boards with the fixed bootloader.

For now, I will try to create a board manager json URL that provides "a fixed boardconfiguration" to enable the users to easily update/flash the correct configured optiboot bootloader.

tuxedo0801 commented 8 years ago

tested a lot with optiboot. On nano and promini. Result:

Optiboot in principle solves the issue, but there are strange side-effects, for example:

I returned to default arduino bootloader and try to avoid the WDT completely, until this issue is solved in arduino bootloader for 328p.

+1 for fixing the existing bootloader.

tuxedo0801 commented 8 years ago

Had a look at the bootloader-code, found this:

https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/bootloaders/atmega/ATmegaBOOT_168.c#L282

#ifdef WATCHDOG_MODS
    ch = MCUSR;
    MCUSR = 0;

    WDTCSR |= _BV(WDCE) | _BV(WDE);
    WDTCSR = 0;

    // Check if the WDT was used to reset, in which case we dont bootload and skip straight to the code. woot.
    if (! (ch &  _BV(EXTRF))) // if its a not an external reset...
        app_start();  // skip bootloader
#else

So MCUSR actually is cleard, but only if WATCHDOG_MODS is enabled?!

tuxedo0801 commented 8 years ago

It is enabled, but not for all AVRs:

https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/bootloaders/atmega/Makefile#L94

tuxedo0801 commented 8 years ago

ping

Are there any side-effects if we enable this for the 328p as well?

tuxedo0801 commented 8 years ago

push

tuxedo0801 commented 8 years ago

push again

We faced the same issue with an ATmega644 ... :-( We try to use the WDT Reset to "reboot" the device via software. But this does not work on 328p and 644. So we use the

asm volatile ("  jmp 0");

workaround, which is actually not really the same.

Would be great if someone could comment on this issue.

va7ta commented 7 years ago

Greetings,

I am the originator of duplicate issue arduino/Arduino#6228. I did not notice this duplication as I encountered the problem prior to having the WDT installed by my app thus I thought it was a different issue. I added WDT code to my app as an after-thought as an attempt to resolve the potential lock-up loop situation.

What I think maybe key to resolving this issue (I apologize in advance if this is just obvious to those in the know) is that in my Nano case a power-off/on cycle reset always restores the program were in contrast neither WDT nor external reset via the reset pin will restore operation. Thus it might be possible to identify the root cause by focusing on the difference between a successful power-on reset and an unsuccessful external pin reset. In any case IMHO the WDT should always be left unconditionally disabled by the boot code until the application setup code specifically initializes it.

va7ta commented 7 years ago

The installation of the optiboot bootloader resolved the WDT lockup issue for my NANO board. I found the information at the following website very helpful:

https://andreasrohner.at/posts/Electronics/How-to-make-the-Watchdog-Timer-work-on-an-Arduino-Pro-Mini-by-replacing-the-bootloader/

I hope those involved with the Arduino IDE development will consider making optiboot the default bootloader for all the 32 pin SMD Atmega328 Arduino boards as is presently done for the UNO.

per1234 commented 6 years ago

@facchinm I'm glad to see https://github.com/arduino/Arduino/commit/1cf34c8250658c5c4a5c488f7a7a0d7071e3430f and to hear that the Nano is being shipped with Optiboot now but I don't think it fully resolves this issue since there has been no move to address the issue for any of the other boards which still use the problematic "ATmegaBOOT" bootloader such as the "Arduino Pro or Pro Mini" board, which was the original topic.

facchinm commented 6 years ago

Indeed, we'll not be producing Pro/Pro mini anymore so there won't be any bootloader update for these boards (following the usual "don't update the bootloader if it's not being flashed in production"). Anyway, I'm reopening the issue to explicitly state that the problem is still there.

Avamander commented 6 years ago

I'll just comment with "Arduino Nano bootloop watchdog timer" for those Googling the issue.

hdrut commented 6 years ago

This solved my issue with Mini Pro:

https://arduino.stackexchange.com/a/45281

rtek1000 commented 6 years ago

Hello everyone,

I understand that there is no interest in updating the bootloader of this model of board if it will not be produced anymore.

But the community is very large, and I believe many would volunteer to correct this.

And I ask, how long until the IDE will be released with the bad bootloader?

Will the man colonize Mars and have not yet solved this bootloader?

Today is August 2018 and since January 2016 has anyone had the idea to fix the bootloader and send for replacement?

Then it would be possible to release the IDE 1.8.6 (Release Notes: Fix the Mini Pro bootloader to WDT finally performed)

rtek1000 commented 6 years ago

One consideration, I was seeing some issues, and I noticed the tag "IDE 1.9.x Beta" so it would be cool instead of 1.8.6 quitting with this fix, "IDE 1.9" having that release note!

Oliv4945 commented 5 years ago

Hi, while a fix integrated in bootloader provided by the IDE would be nice, switching to MiniCore works well.

kai-morich commented 4 years ago

Instead of switching to alternative bootloader, I used a free timer + pin to create a custom watchdog:

class Watchdog {
  public:

  void init() {
    TCCR1A = _BV(COM1A0);// OC1A toggle
    TCCR1C = _BV(FOC1A); // toggle manually, else would start initially LOW
    TCNT1 = 0;
    TCCR1B = _BV(CS12);  // start timer with clk/256 => overflow after 2sec @ 8MHz
    pinMode(9, OUTPUT); // = OC1A
  }

  void reset() {
    TCNT1 = 0;
  }
};

and connect OC1A (pin 9) with diode --|<|--- to RST

Dancofra commented 4 years ago

fix the WatchDog problem with the Arduino Promini loaded the optiboot_atmega328.hex to the Arduino Promini,

loaded the new project from the Arduino IDE selected the Arduino UNO and the COM port

optiboot-master: https://github.com/Optiboot/optiboot

works very well ---- it is just loading the programs as if it were for an Arduino UNO

#include <avr/wdt.h>

void setup(){
  Serial.begin(9600);
  Serial.println("Setup started :");
  // make a delay before enable WDT 
  // this delay help to complete all initial tasks
  delay(2000);
  wdt_enable(WDTO_4S);
}

void loop(){
  Serial.println("LOOP started ! ");
  for(int i=0; i<=5; i++){
    Serial.print("Loop : ");
    Serial.print(i);
    Serial.println();
    delay(1000);
    wdt_reset();
  }
  //infinity loop to hang MCU
  while(1){}
}
chomchom69420 commented 1 year ago

Hello, raising this issue after a long time.

I am working on an assignment where I have to force restart an atmega328 using the wdt. I am clearing the WDIE bit to stop the interrupt and directly move into system reset. Here is the code for the function:

void wdt_force_restart()
{
    //disables interrupt
    SREG &= ~(1<<I_SREG);

    //Enabling change
    WDTCSR |= (1<<WDCE);

    //Clearing WDIE
    WDTCSR &= ~(1<<WDIE);

    //Wait for reset
    while(1);
}

This should reset my atmega and it should print out the initialization lines as given here:

int main(void)
{
    /* initialize the hardware and device state */
    config_init();
    vpd_init();
    rtc_init();
    log_init();
    alarm_init();
    uart_init();
    led_init();
    temp_init();
    wdt_init();
    tempfsm_init();
    unsigned char connected = 0;  /* 1 if socket is connected, otherwise, 0 */
    /* print the banner to the debug port */
    uart_writestr("SER486 Project 3 - Integration\r\n");
    uart_writestr( STRINGIZE_VALUE(YOURNAME) );
    uart_writestr("\r\n");
   .
   .
}

The above code is from the main.c file.

I am using the simulavr platform to simulate the code. Whenever I request a reset, the device is getting stuck in the infinite while() loop and not resetting after 2s (which is the time I have set up as below):

void wdt_init()
{
    //Clear WDRF in MCUSR
    //MCUSR &= ~(1<<WDRF);

    //Setting the pre-scalar for timeout period of 2s
    //WDTCSR |= (1<<WDP0) | (1<<WDP1) | (1<<WDP2);

    //Interrupt and system reset mode
    WDTCSR |= (1<<WDIE) | (1<<WDE);

    //Initizaize global interrupts
    SREG |= (1<<I_SREG);
}

Could anyone suggest a fix for this issue? Really appreciate it. :)

Is there a way of changing the bootloader in simulavr, as I can see above apparently switching to Optiboot helps. I don't know much about simulavr and I am not sure what bootloader it uses by default.

per1234 commented 1 year ago

Hi @chomchom69420. Thanks for your interest in this open source project. This issue thread is only to be used for discussion directly relevant to the resolution of the reported bug. The discussion of your project is more appropriate for the Arduino Forum. I'm sure we will be able to help you out over there:

https://forum.arduino.cc/

mirh commented 1 year ago

we'll not be producing Pro/Pro mini anymore so there won't be any bootloader update for these boards (following the usual "don't update the bootloader if it's not being flashed in production").

While reading on #308, an incredible idea came to my mind. Why don't you make available an updated bootloader, but it's a separate option in the IDE just like you already have on the Nano? Make it even non-default if you really want to be conservative, make the name scary or stick a big BETA label if your years-long testing still hasn't gone through, but this way you could make everyone happy.

EDIT: this was also suggested in #141 I see

rtek1000 commented 1 year ago

Hello, I fell back into this bad Bootloader hole, on a Pro Mini.

The board is a bit difficult to access, so updating the bootloader via ISP is a bit tricky now.


I've seen something about making a sketch that can update the bootloader, but it seems to be something obscure that not many people have tried:

Ref.: Update bootloader using specialy crafted Arduino sketch


But I managed to get out of the state of flashing (forever) the LED,

I noticed that when powering the board, it takes a long time for the LED (pin 13) to start blinking, but after the LED is blinking, when RESET is pressed, the LED blinks quickly again, so the bootloader does not have time to rewrite the sketch

Steps:

1- Activate "compilation" and "upload" LOGs (verbose output) in preferences (restart IDE)

2- Completely turn off the Pro Mini power supply, including the USB Serial adapter

3- Press and hold RESET (keep pressing RESET until the middle of step 6) on the Pro Mini board (this is fundamental to work)

4- Connect the USB Serial adapter (which will also power the Pro Mini board)

5- Check and select the port again in the Arduino IDE (may happen if the system re-enumerates the port)

6- Upload a sketch without WDT [without wdt_enable()] to the Pro Mini board, after compiling and reaching the Upload part, where orange letters appear, release the Pro Mini RESET button, this should give the necessary time for the bootloader to work

(Tested with: Arduino IDE 1.8.19, Linux OS and Red FTDI Type USB Adapter)