On Mon, 20 Dec 2010, KL wrote:

.at least it looks like that.

Foreword: ATmega16A, 4 MHz, nothing special peripheral devices, just stupid
Nokia1100 display.

In my device, Watchdog disabling routine were used frequently enough (every
second). Sometimes device was reset. (Oh, that boring "sometimes".)
I found why.

wdt_disable routine (wdt.h) works like this:
1) Save SREG
2) cli
3) WD_CONTROL_REG = _BV(_WD_CHANGE_BIT) | _BV(WDE)
4) WD_CONTROL_REG = 0
5) Restore SREG

Looks like ok, yeah?
But look at (3). This line not only sets WD_CHANGE and WDE bits. In addition
it resets to zero WDT prescaler bits. This makes WD work at maximum speed.
If WDT_RESET was not performed recently enough, line (3) will reset device
immediately.
Even if I would write
        wdt_reset();
        wdt_disable();
I can stiil catch an interrupt right between reset and disable.
Sure, I can write ATOMIC_BLOCK, but all this becomes too bulky.

Workaround:
a) Add wdr between lines (2) and (3)
Or
b) Replace (3) to something that saves prescaler settings.

Preservation isn't necessary.
Setting the prescale bits to the slowest available would also do the trick.
It has the advantage of allowing a constant.

--
Michael   [email protected]
"Pessimist: The glass is half empty.
Optimist:   The glass is half full.
Engineer:   The glass is twice as big as it needs to be."

_______________________________________________
AVR-chat mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/avr-chat

Reply via email to