Reseting in Software

Hello,

is there a way to reset the Arduino (well, it is an ATmega644, programmed with the bootloader from here)?

I have read a bit and found out you can only use the WDT timer, but it seams the Arduino bootloader was in the way for this. Is it the same for the ATmega644 bootloader?

Jan

It would be much better if you fixed the problem that requires you to reset the Arduino.

It's not a problem, it's a feature. Then I send a specific command via Serial, the board should "start from the beginning", with other words, reseting.

Jan

Then I send a specific command via Serial, the board should "start from the beginning", with other words, reseting.

What is it that you think "start from the beginning" should do? Resetting the Arduino is almost certainly not what needs to be done. If it really is, just close and reopen the serial port. The Arduino will reset when you do that.

What is it that you think "start from the beginning" should do?

Reinit all variables, simply start everything from the beginning, as if the power just would have been connected.

If it really is, just close and reopen the serial port.

Ahh.. If it only would be so simple...

Ok, the problem is, I have to disable to serial reset, because it may happen the ATmega "changes master" (program controlling it). But, I still need to reset it at some points, so for that I need to have a reset command that executes a software reset.

Jan

EDIT: Small change: In my first post I sad the wrong link for the bootloader. I use the bootloader from here, it's the core files I'm using from avr-developers.

You could do the same "call 0" that the bootloader does; as has been pointed out many times here before (I'm a little surprised your search didn't find them), it isn't exactly a reset, but it is as close as you can get with a software-only solution, unless you invoke the watchdog.

Do you mean "asm volatile ("jmp 0x0000");" when you say "call 0"?

If yes; that isn't enough, the variables wouldn't be reinited then.
If no; haven't found anything like that, what exactly does it do?

I don't have any problems with using the WDT timer, but:

I have read a bit and found out you can only use the WDT timer, but it seams the Arduino bootloader was in the way for this. Is it the same for the ATmega644 bootloader?

Jan

the variables wouldn't be reinited then

Why not?

Do you mean "asm volatile ("jmp 0x0000");" when you say "call 0"?

No, when I say "call", I mean "call".

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

(Source: ATmegaBOOT_168.c)

Because:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1242847196 Third post
Answerpot.com is for sale | HugeDomains Second post

There are other, similar posts on the net too.

Jan

I presume you're referring to this:

All of the chip's registers, settings and RAM will not be properly initialized.

As far as your sketch is concerned, it will appear as though it has just been booted for the first time, because it will have followed the same path through the pre-"main" initialisation of your sketch.

Ok, I didn't knew that. How is it with the registers?

All of the chip's registers, settings and RAM will not be properly initialized.

Ups... Didn't see that.

Ok, thanks!

Jan

Jumping to 0x0000, IMHO is a total kludge.
Why are people afraid of correcting the bootloader when there is a problem?
It is open source.....
Just fix the bootloader and be done with it so you can do a real software driven reset
if that is what you want.
Unlike jumping to 0x000, it allows everything to start up clean and fresh.

Jan, the 644 seems to be using an older version of the atmegaBOOT bootloader but the fix
should be the same:
In the bootloader:

Replace this:

#ifdef ADABOOT          // BBR/LF 10/8/2007 & 9/13/2008
    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
#endif

with this:

#ifdef ADABOOT
	ch = MCUSR;
	MCUSR = 0;
	wdt_disable();

	// 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
	asm volatile("nop\n\t");
	MCUSR = 0;
	wdt_disable();
#endif

Build a new bootloader and then burn it in your chip and enjoy.

Now if you have recent gcc tools, you may also find that your bootloader may no
longer compile.

If you have errors releated to EECR or EEPE,
you will need to also make this change:
Add this up at the top:

#include <avr/eeprom.h>

then change this:

                                        while(EECR & (1<<EEPE));

to

                                        while(!eeprom_is_ready());

Then it should compile again.
Once you get it in your AVR, you can use something like this to reset the AVR:
Sample sketch to demonstrate software control of reset:

#include <avr/wdt.h>

void setup()
{
	Serial.begin(9600);
	Serial.println("setup()");
}
	
void loop()
{
	Serial.println("Top of loop()");
	for(int x = 3; x ; x--)
	{
		Serial.println(x);
		delay(1000);
	}
	Serial.println("Reseting Arduino");
#if ARDUINO >= 100
        delay(50); // wait for transmission to finish
#endif
	resetArduino();
}

void resetArduino()
{
	wdt_enable(WDTO_15MS);
	noInterrupts();
	while(1); // wait to die and be reborn....
}

If your watchdog reset is working, you will see the messages repeating.
If you have a broken WDT bootloader, you will see it the first time and
then the chip will hang in the bootloader until you manually reset it.
--- bill

Thanks, I will test that when I get home.

Jan

Hm.. it compiled without problems, but:

.....\hardware\atmega324_644\bootloaders\atmega644p>avrdude -cdragon_isp -patmega644 -P usb -U flash:w:ATmeg
aBOOT_644_NEW.hex

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.18s

avrdude: Device signature = 0x1e9609
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed

         To disable this feature, specify the -D option.
avrdude: conflicting -e and -n options specified, NOT erasing chip
avrdude: reading input file "ATmegaBOOT_644_NEW.hex"
avrdude: input file ATmegaBOOT_644_NEW.hex auto detected as Intel Hex
avrdude: ERROR: address 0x10010 out of range at line 130 of ATmegaBOOT_644_NEW.h
ex
avrdude: write to file 'ATmegaBOOT_644_NEW.hex' failed

avrdude: safemode: Fuses OK

avrdude done.  Thank you.

Why this???

Jan

I believe that you have to use the -e option which also erases the fuses when you program the
flash.

Do you know the value for your 644 fuses?

I'd update the Makefile to include a rule to burn the flash to avoid
typing in the long command line.

I've updated my arduino AmetaBOOT makefile to support doing all this in one avrdude command
for the Dragon as the current avrdude has a bug in it such that back to back avrdude commands
will fail on the dragon. (I also have a patch for that but the avrdude maintainer refuses to accept
it - but that is another story).

Here is the definition that I use:

# enter the parameters for the avrdude isp tool
ISPTOOL = dragon_isp
ISPPORT	   = usb
ISPSPEED = 

# the efuse should really be 0xf8; since, however, only the lower
# three bits of that byte are used on the atmega168, avrdude gets
# confused if you specify 1's for the higher bits, see:
# http://tinker.it/now/2007/02/24/the-tale-of-avrdude-atmega168-and-extended-bits-fuses/
#
# similarly, the lock bits should be 0xff instead of 0x3f (to
# unlock the bootloader section) and 0xcf instead of 0x0f (to
# lock it), but since the high two bits of the lock byte are
# unused, avrdude would get confused.

ISPFUSEFLASH = avrdude -c $(ISPTOOL) -p $(MCU_TARGET) -P $(ISPPORT) $(ISPSPEED) \
-e -u -U lock:w:0x3f:m -U efuse:w:0x$(EFUSE):m -U hfuse:w:0x$(HFUSE):m -U lfuse:w:0x$(LFUSE):m \
-U flash:w:$(PROGRAM).hex -U lock:w:0x0f:m

This single command was a modification of their existing fuse burning methodology.
When using the dragon you can remove the initial "-U lock:w:0x3f:m" as it is not needed.
Not sure if other programmers need it as some of them ignore the erase
command and only erase things when new data is written.

You will need to define EFUSE, HFUSE, and LFUSE
I assume the 644 has 3 fuses? and I'm not sure what those are or
what the final lock bits need to be for that part.

you will then need a rule to to the actual burn.
Something like this near the bottom of the makefile:

program: $(PROGRAM).hex
	$(ISPFUSEFLASH)

You can then do "make program" to program the part.
Make sure you use a in the program rule above rather than spaces
as make after 35+ years still requires tabs rather than whitespace as lead in separators.

Actually -e on avrdude may not erase the fuses, but it definitely erases the lock bits.
I've always set the fuses at the same time using the -u option so I'm not really sure.

You might be able to just use the -e option on what you had and then set the lock bits
when done and not have to mess with the fuses.

--- bill

I managed to burn the bootloader through AS5.

But, now, trying to upload the sketch, I get this error:

Binary sketch size: 11082 bytes (of a 63488 byte maximum)
avrdude: verification error, first mismatch at byte 0x0002
0x7a != 0x38
avrdude: verification error; content mismatch

Why?

Jan

What about the fuses & lock bits?
Were they restored when the bootloader was burned?

I can check that. What should they be?

Jan