[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[avr-chat] wdt_disable bug found
From: |
KL |
Subject: |
[avr-chat] wdt_disable bug found |
Date: |
Mon, 20 Dec 2010 11:13:08 +0300 |
.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.
Best regards,
{Kreyl}
- [avr-chat] wdt_disable bug found,
KL <=