Software reset on new Arduino's possible or not?

I have been reading about the possibility of resetting your arduino trough the sketch itself. Some say it's not possible others say it can be done.

Now for the newer Arduino duemilanove, uno and ethernet, I would say, you can, if you connect a capacitor from a digital pin to the reset pin. In your sketch you'll only have to put that same pin to high.

Is this correct?

This would help in projects where you can setup things like IP, MASK, MAC, ... other setup decisions and need the arduino to reboot for using the new setup values.

PS: doesn't the arduino reset when you open the Serial Monitor or when you upload a sketch?

Yes, in fact, if you look at the bootloader source code, the "reset" is simple; just start executing at address 0x0000:

(viewing /Applications/Arduino.app/Contents/Resources/Java/hardware/arduino/bootloaders/atmega/ATmegaBOOT_168.c on my Mac)

void (*app_start)(void) = 0x0000;

^ that defines a function pointer "app_start()" whose location goes to 0x0000

#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

just running app_start(); will then jump to the first instruction in Flash. At that point your sketch's compiled hex code should re-setup all its data, stack pointers, etc.

Note: I'm not sure if that resets the state of all the I/O registers though, so it might not be as clean as a true hardware reset...

Mmm, I just realized that my own solution is a hardware reset invoked by software :smiley:

Your solution is actually a software reset, now I'll have to test that one out. Not sure it will be enough to just jump to the first instruction in Flash, but there's only one way to find out.

Jumping to 0 works fine, technically it's not the same but I doubt there's any practical difference.

I use

asm ("jmp 0");

but there was a different approach posted somewhere yesterday with a pointer to a function defined to be at 0.


Rob

but there was a different approach posted somewhere yesterday with a pointer to a function defined to be at 0.

I just lifted it straight from the bootloader source.

In your sketch you'll only have to put that same pin to high.

Is this correct?

No it is not. This is because the pin gets set to an input part way through the reset process and so the reset is not completed. The data sheet warns against this.
Jumping to the reset vector will not do everything a hardware reset will. While it will start the program again it will not reset the I/O pins or other things to the default state.
One way of getting a true reset is to have a pin trigger a monostable like an NE555 or 74LS121 (or 74LS123) and have the output of the monostable drive the reset pin. That way you can ensure the full time on the reset pin.

If my reading of the datasheet is correct, another way to do a full reset from software would be to enable the watchdog timer with its minimum timeout of 16ms and watchdog reset enabled. Then just sit in a loop forever - it will time out and reset after 16ms.

.. just tried using the watchdog to do a hardware reset and it works. Just do this to cause a reset:

noInterrupts();
WDTCSR = 0x98;
for(;;){}

[EDIT: on further invstigation, the following is better because it guarantees to set the watchdog time to the minimum of 16ms:

noInterrupts();
__asm("wdr");
WDTCSR = (1<<WDCE) | (1<<WDE);
WDTCSR = (1<<WDE);
for(;;){}

]

Yep, that should work, something like

WDTCSR = (1<<WDE);
while (1);

IIRC.


Rob

The problem with the watch dog is that if you set it too short you will never get program to run in the first place because the boot loader takes a bit seeing if there is a download ready.

There have been instances of people bricking their arduino doing this and only disabling the watchdog by reprogramming the fuses have they been recovered. Of course no problem if you have a programmer but a pain if you have not.

Grumpy_Mike:
The problem with the watch dog is that if you set it too short you will never get program to run in the first place because the boot loader takes a bit seeing if there is a download ready.

There have been instances of people bricking their arduino doing this and only disabling the watchdog by reprogramming the fuses have they been recovered. Of course no problem if you have a programmer but a pain if you have not.

It works fine for me on an Arduino Uno when I set the watchdog timeout to the minimum value of 16ms. I note that the optiboot bootloader initialises the watchdog very early on. Possibly there could be a problem if there are other bootloaders that don't re-initialise or disable the watchdog.

It works fine for me on an Arduino Uno when I set the watchdog timeout to the minimum value of 16ms. I note that the optiboot bootloader initialises the watchdog very early on. Possibly there could be a problem if there are other bootloaders that don't re-initialise or disable the watchdog.

That was the problem with the original 'arduino' bootloader and many of it's decendents, the WDT interrupt would just keep the bootloader from timing out and jumping to the sketch code. I think Lady Ada was the first to offer a arduino compatible bootloader which handles the WDT correctly and that same method of handling WDT then applied to the uno bootloader. I don't have a list of which bootloaders don't handle WDT correctly.

Lefty

One way of getting a true reset is to have a pin trigger a monostable like an NE555 or 74LS121 (or 74LS123) and have the output of the monostable drive the reset pin. That way you can ensure the full time on the reset pin.

but is a capacitor not able to feed the reset pin the full time needed to get a hard reset?

but is a capacitor not able to feed the reset pin the full time needed to get a hard reset?

No.

but is a capacitor not able to feed the reset pin the full time needed to get a hard reset?

No.

I don't understand why, but I accept that.

This code from dc42 works for me on my Arduino Ethernet, but I do think (pretty sure) void setup (){} isn't executed again

void reset(){
  noInterrupts();
  __asm("wdr");
  WDTCSR = (1<<WDCE) | (1<<WDE);
  WDTCSR = (1<<WDE);
  for(;;){};
}