What doesn't get reset after the watchdog expires?

Greets,

I'm using the watchdog timer to reboot an Arduino after a hard error. The code sets a watchdog timer 1 second in the future and reports the error. Once I get comfy with how this is working out, I'll make the watchdog time shorter -- just long enough for a Modbus parity error exception to make it out the wire.

My preference would be that all the inputs and outputs get left alone -- all the digital outputs are left as outputs, high or low, etc. and all the digital inputs are left as inputs. What does and ATmega 328 actually do? The ATmega 328 data sheet says the pins are tri-stated for a "reset", but the block diagram makes it look like that only applies to power on, brown-out and reset pin resets.

You can set the WDT to interrupt instead of reset. Then you can handle the timeout any way you like.

To answer the original question: 10. System Control and Reset 10.1 Resetting the AVR During reset, all I/O Registers are set to their initial values, and the program starts execution from the Reset Vector. [...] 10.2 Reset Sources The ATmega48A/48PA/88A/88PA/168A/168PA/328/328P has four sources of reset: • Power-on Reset. The MCU is reset when the supply voltage is below the Power-on Reset threshold (VPOT). • External Reset. The MCU is reset when a low level is present on the RESET pin for longer than the minimum pulse length. • Watchdog System Reset. The MCU is reset when the Watchdog Timer period expires and the Watchdog System Reset mode is enabled. • Brown-out Reset. The MCU is reset when the supply voltage VCC is below the Brown-out Reset threshold (VBOT) and the Brown-out Detector is enabled.

So, yes, the Watchdog System Reset will set all I/O pins to INPUT.

Thanks! Foiled by a misleading block diagram!

Now for the next question, because this was not the answer I was hoping for -- is all of the internal RAM re-initialized to 0x00, or only the space from 0x0000 through &_end? There's some state I'd like to save before the watchdog reset and I don't want to write it to EEPROM due to it having a limited life expectancy. What I'm thinking about doing is something like this --

extern int _end;

save_state = (&_end) + 1; *saved_state = stuff to save;

then after reboot, if the reason was a watchdog expiry,

stuff to save = *saved_state;

If the startup code doesn't zero past _end, this should work, provided there wasn't a heap / stack collision between the time the watchdog expired and the setup() function was re-entered. Oh, and provided malloc() or someone else doesn't stomp all over it ...

I had a quick look at 328's datasheet, but I didn't find anything about the sram state after a reset.

TBH, I find it strange to completely reset the chip whenever a timeout on a bus occurs. Wouldn't it be simpler to just react to the timeout in some way, instead of resetting and worrying about how to retain the ram state (which would be easily accomplished by just continuing to run the program :-) ?

I have guard data in SRAM. If the guard bytes have been over-written, I have to assume the memory is corrupt and the device needs to be reset. So far this hasn't happened, but I have to make sure it DOESN'T happen.

What would be better is something with more SRAM. I'm currently stuffing 10 pounds of fertilizer in a 5 pound sack. An Arduino based on the ATmega 645P would be sweet. Depending on how much money I have to spend on building my own, I may wind up going that route -- replacing the 328P with the 645P or similar. The ATmega 2560 is too much, in all ways of being "too much". And the 328 and friends is "too little", in all ways of being "too little". It's like those d@mned three bears -- I want my Arduino "Just Right" :)

jfhaugh: ... is all of the internal RAM re-initialized to 0x00, or only the space from 0x0000 through &_end?

No RAM would be initialized by the processor. The C runtime library would initialize static variables. I seem to recall someone a while back had a sketch that counted resets somehow.

I'm tempted to suggest you redesign so something like a parity error can be handled less obtrusively than a system reset.

I want my Arduino “Just Right”

ATmega644 or ATmega1284, perhaps?

RESET does not clear RAM or the GP registers (as discovered the hard way on Arduino), but the IO registers mostly have defined states after reset. The C startup code clears memory and sets GP registers to known states, but usually doesn’t touch most of the IO registers.

If your RAM is corrupted, you really don’t have any assurance that the IO ports are in their correct states, either. The usual reason for a WD reset is “things are so screwed up that I’m better off starting from scratch than trying to continue.”

[quote author=Nick Gammon link=topic=92100.msg692755#msg692755 date=1329368677] No RAM would be initialized by the processor. The C runtime library would initialize static variables. I seem to recall someone a while back had a sketch that counted resets somehow.

I'm tempted to suggest you redesign so something like a parity error can be handled less obtrusively than a system reset. [/quote]

Does the C RTL zero =all= of SRAM, or only from the start of data (I think that's 0x0100) through _end? That's the question -- just how "cleared" does the RTL clear?

There's always a point where "throw up hands and start over" is the only remaining solution. I have done fault-tolerant programming in the past, but there was always more memory for maintaining the needed data structures.

In the case of this device, the device driver on the data logger is written in such a way that if the ATmega reboots, it's no big deal. For the relays, for example, if the "reported relay state" differs from the "requested relay state", a "force coil" Modbus command will be sent once that difference is detected further up the software stack. There are some upcoming changes to the ATmega firmware that will require that the entire state be reset after a reboot, but I'll burn that bridge when I get there.

Right now I'm trying to restore output pin states faster than it will take for the Modbus "read coils" and "force coil" commands to do that. If I can do that in fewer than 10 AC cycles (167ms), I'd be happy. If I can do that in under 3 AC cycles (50ms), I'll jump for joy. Both of those goals require that I can have the state tucked away in some special place in SRAM and not have it zero'd across resets.

jfhaugh: Does the C RTL zero =all= of SRAM

No. The bss section is zeroed. The data section is copied from Flash. The rest is left untouched.

Udo Klein has something that may help... http://arduino.cc/forum/index.php?topic=56809.0.html

Bear in mind that the memory is [u]not initialized, ever[/u]. It will have "random" data in it after power-up.

On a side-note, I suspect Udo could not get it working reliably because of this problem... http://arduino.cc/forum/index.php/topic,84243.0.html

Right now I'm trying to restore output pin states faster than it will take for the Modbus "read coils" and "force coil" commands to do that. If I can do that in fewer than 10 AC cycles (167ms), I'd be happy. If I can do that in under 3 AC cycles (50ms), I'll jump for joy. Both of those goals require that I can have the state tucked away in some special place in SRAM and not have it zero'd across resets.

Just remember that Atmel makes no guarantees about the state of SRAM after a reset. At a minimum, you should put magic values on each end of the data and include a CRC.

I don't want to write it to EEPROM due to it having a limited life expectancy

You expect more than 100,000 writes during the lifetime of the device?

[quote author=Coding Badly link=topic=92100.msg693461#msg693461 date=1329419067]

jfhaugh: Does the C RTL zero =all= of SRAM

No. The bss section is zeroed. The data section is copied from Flash. The rest is left untouched.

Udo Klein has something that may help... http://arduino.cc/forum/index.php?topic=56809.0.html

Bear in mind that the memory is [u]not initialized, ever[/u]. It will have "random" data in it after power-up.

On a side-note, I suspect Udo could not get it working reliably because of this problem... http://arduino.cc/forum/index.php/topic,84243.0.html

Right now I'm trying to restore output pin states faster than it will take for the Modbus "read coils" and "force coil" commands to do that. If I can do that in fewer than 10 AC cycles (167ms), I'd be happy. If I can do that in under 3 AC cycles (50ms), I'll jump for joy. Both of those goals require that I can have the state tucked away in some special place in SRAM and not have it zero'd across resets.

Just remember that Atmel makes no guarantees about the state of SRAM after a reset. At a minimum, you should put magic values on each end of the data and include a CRC.[/quote]

I believe there is a "reset reason" status register that can tell me if I reset due to reset pin, power on or watchdog reset. If the reason is "watchdog reset", I can assume (hah!) that my value is correctly stored in some secret, magical, non-BSS location.

I don't want to write it to EEPROM due to it having a limited life expectancy

You expect more than 100,000 writes during the lifetime of the device?

D'oh! I mixed up FLASH cycles and EEPROM cycles. I'll have to look at using EEPROM to store state before the watchdog reset is scheduled. There are times when I'm glad to feel embarrassed ...

I seem to recall someone a while back had a sketch that counted resets somehow.

I think that was me :-)

http://arduino.cc/forum/index.php?topic=86624.0

mromani:

I seem to recall someone a while back had a sketch that counted resets somehow.

I think that was me :-)

http://arduino.cc/forum/index.php?topic=86624.0

Looks nice. I'll have to steal it :)

Thanks :-)

mromani: I think that was me :-)

I'm glad someone's memory is better than mine. ;)

At least I remembered it existed.

jfhaugh: I believe there is a "reset reason" status register that can tell me if I reset due to reset pin, power on or watchdog reset.

Page 54 of the datasheet:

The MCU Status Register (MCUSR) provides information on which reset source caused an MCU reset.

Note that the bootloader intercepts hardware resets, and may eat/clear the cause. Even if not, the mechanism used for starting the sketch is ... a watchdog reset. So by the time an Arduino sketch runs, the reset reason will ALWAYS be "Watchdog Reset." (This ensures that the sketch starts running is as close to a "freshly reset" condition as possible.") (hmm. There's a "fast start" feature that skips the bootloader on poweron, so this might not always be true.)

Years ago I read a paper about this very thing. They tested SRAM after resets. Their conclusion for their device was that memory was largely left intact. In fact, it it failed to pass a checksum 1 out of x (some large numbers, sorry, slept since then) resets. I mention this because I believe the quoted advice above is spot on.

If you can’t verify your memory after a reset, best to re-initialize everything to a known good state. Personally, this is what I’d attempt to do given Atmel makes no guarantees about SRAM state.