¨Watchdog funny behaviour (ATmega168)

Go To Last Post
8 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have never used the watchdog before but I expected it to be easy to set up just like most other things. I soon had it working and after realizing that it would stay enabled after reset (oups) most was OK.

But there is one strange thing. I had to enable the watchdog twice to make it take the prescaler bits! I followed the instructions of the datasheet at the description of WDTCSR. First write WDCE and next WDE + prescaler.
But this is obviously wrong way to do it! It works but the prescaler bits will be set the SECOND time I make the operation.
I wasn't satisfied by this unpredicted behavior so I searched the datasheet for more information and found that to disable the Watchdog, the write operation is slightly different than from what you get from reading the description of WDTCSR.
First write WDCE AND WDE, next write WDE (1 or 0). I changed the enable sequence to the same and now it works the first time.
First write WDCE and WDE, second write WDE + prescaler.

If the correct operation is as described it is very strange that it still works to turn it on with the first method. Turning off works even if I follow the first method, it even writes (only tested to cleared them) the prescaler bits..

My favorites:
1. My oscilloscope, Yokogawa DLM2024.
2. My soldering iron, Weller WD2M, WMRP+WMRT.
3. JTAGICE3 debugger.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There is a fairly extensive thread on setting up the watchdog on that model series--try to hunt it out.

AFAIK after the initial "getting used to" the (at that time) new feature of watchdog interrupt, nowadays the CodeVision Wizard and GCC facilities (macros?) are correct.

To go further, I think you'll need to show some code of the working and non-working sequences. And the actual generated code.

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sure, here is example code:

// macros and variables used:
// unsigned char temp;
// #define SetBit(x,y) (x|=(1<<(y)))      // Sets bit no y in x
// #define SetBitMask(x,y) (x|=((x)|(y))) // Sets bit masked by y in x
// #define ClrBit(x,y) (x&=~(1<<(y)))     // Clears bit no y in x
// #define BIT(x)	(1 << (x))

// Turn on WDT, prescaler will not be set.
temp = BIT(WDE) | prescaler;	// Must use predefined variable to secure
															// write withn 4 clock cycles.
SetBit(WDTCSR,WDCE);	// Enables following change of WDT
WDTCSR = temp;				// Activate watchdog timer in System Reset Mode.

// Repeat, prescaler will be set.
temp = BIT(WDE) | prescaler;	// Must use predefined variable to secure
															// write withn 4 clock cycles.
SetBit(WDTCSR,WDCE);	// Enables following change of WDT
WDTCSR = temp;				// Activate watchdog timer in System Reset Mode.

// Turn off WDT (including clearing prescaler)
ClrBit(MCUSR,WDRF);
temp = 0;
SetBit(WDTCSR,WDCE);
WDTCSR = temp;

// Turn on WDT, prescaler will be set.
temp = BIT(WDE) | prescaler;	// Must use predefined variable to secure
															// write withn 4 clock cycles.
SetBitMask(WDTCSR,BIT(WDCE)|BIT(WDE));	// Must set WDE here also or prescaler will not be set first time.
WDTCSR = temp;				// Activate watchdog timer in System Reset Mode.

Including assembler:

49:       temp = BIT(WDE) | prescaler;	// Must use predefined variable to secure
+00000F79:   2F62        MOV       R22,R18        Copy register
+00000F7A:   6068        ORI       R22,0x08       Logical OR with immediate
51:       SetBit(WDTCSR,WDCE);	// Enables following change of WDT
+00000F7B:   91800060    LDS       R24,0x0060     Load direct from data space
+00000F7D:   6180        ORI       R24,0x10       Logical OR with immediate
+00000F7E:   93800060    STS       0x0060,R24     Store direct to data space
52:       WDTCSR = temp;				// Activate watchdog timer in System Reset Mode.
+00000F80:   93600060    STS       0x0060,R22     Store direct to data space
55:       temp = BIT(WDE) | prescaler;	// Must use predefined variable to secure
+00000F82:   2F62        MOV       R22,R18        Copy register
+00000F83:   6068        ORI       R22,0x08       Logical OR with immediate
57:       SetBit(WDTCSR,WDCE);	// Enables following change of WDT
+00000F84:   91800060    LDS       R24,0x0060     Load direct from data space
+00000F86:   6180        ORI       R24,0x10       Logical OR with immediate
+00000F87:   93800060    STS       0x0060,R24     Store direct to data space
58:       WDTCSR = temp;				// Activate watchdog timer in System Reset Mode.
+00000F89:   93600060    STS       0x0060,R22     Store direct to data space
61:       ClrBit(MCUSR,WDRF);
+00000F8B:   B784        IN        R24,0x34       In from I/O location
+00000F8C:   7F87        ANDI      R24,0xF7       Logical AND with immediate
+00000F8D:   BF84        OUT       0x34,R24       Out to I/O location
62:       temp = 0;
+00000F8E:   2766        CLR       R22            Clear Register
63:       SetBit(WDTCSR,WDCE);
+00000F8F:   91800060    LDS       R24,0x0060     Load direct from data space
+00000F91:   6180        ORI       R24,0x10       Logical OR with immediate
+00000F92:   93800060    STS       0x0060,R24     Store direct to data space
64:       WDTCSR = temp;
+00000F94:   93600060    STS       0x0060,R22     Store direct to data space
67:       temp = BIT(WDE) | prescaler;	// Must use predefined variable to secure
+00000F96:   2F62        MOV       R22,R18        Copy register
+00000F97:   6068        ORI       R22,0x08       Logical OR with immediate
69:       SetBitMask(WDTCSR,BIT(WDCE)|BIT(WDE));	// Must set WDE here also or prescaler will not be set first time.
+00000F98:   91800060    LDS       R24,0x0060     Load direct from data space
+00000F9A:   6188        ORI       R24,0x18       Logical OR with immediate
+00000F9B:   90200060    LDS       R2,0x0060      Load direct from data space
+00000F9D:   2A28        OR        R2,R24         Logical OR
+00000F9E:   92200060    STS       0x0060,R2      Store direct to data space
70:       WDTCSR = temp;				// Activate watchdog timer in System Reset Mode.
+00000FA0:   93600060    STS       0x0060,R22     Store direct to data space

My favorites:
1. My oscilloscope, Yokogawa DLM2024.
2. My soldering iron, Weller WD2M, WMRP+WMRT.
3. JTAGICE3 debugger.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm not going to waste time checking your watchdog code since you can use

#include 
wdt_enable_ISR(WDTO_2S); // enable a 2 sec. w.dog.

I see you're not using GCC, but doesn't your Compiler have the equivalents ? If not, look at how GCC defines its wdt.h and do the same. Then you're all done.

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am done, it is working. I am pretty sure that GCC do the same as I do. But the behavior is weird. If I fall upon something that do not correspond to the datasheet it is a good reason to dig a little bit deeper. The chip just shouldn't behave like this.
(I use Imagecraft).

Maybe someone who have an installation of gcc can make a comparison?

My favorites:
1. My oscilloscope, Yokogawa DLM2024.
2. My soldering iron, Weller WD2M, WMRP+WMRT.
3. JTAGICE3 debugger.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

In my datasheet it says

1. In the same operation, write a logic one to the Watchdog change enable bit (WDCE) and WDE. A logic one must be written to WDE regardless of the previous value of the WDE bit.
2. Within the next four clock cycles, write the WDE and Watchdog prescaler bits (WDP) as desired, but with the WDCE bit cleared. This must be done in one operation.

It seems like what you ended up doing.

TTS

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

From wdt.h (ampersand is percent sign):

#define   wdt_enable(value)  \
_asm__ __volatile__ (  \
    "in _tmp_reg_, __SREG__" "\n\t" \
    "cli"  "\n\t"    \
    "wdr"  "\n\t"    \
    "sts  &0, &1"  "\n\t"   \
    "out  __SREG__, __tmp_reg__"  "\n\t"  \
    "sts  &0, &2"  "\n\t"   \
    : /* No outputs */      \
    : "M" (_SFR_MEM_ADDR(_WD_CONTROL_REG)),  \
      "r"  (_BV)_WD_CHANGE_BIT) | (_BV(WDE)),   \
      "r"  ((uint8_t)  ((value & 0x08 ? _WD_PS#_MASK : 0x00) | \
           _BV(WDE) | (value & 0x07))  \
    : "r0"    \
)

This code works, and shows that your posted code sequence isn't right. You try to write to prescaler bits on 1st write. You're supposed to write to WCE and WDE bits ONLY on first time. In your OP, your first try is the WRONG seq. and second try is according to the datasheet. No mystery goin' on here.

1) Studio 4.18 build 716 (SP3)
2) WinAvr 20100110
3) PN, all on Doze XP... For Now
A) Avr Dragon ver. 1
B) Avr MKII ISP, 2009 model
C) MKII JTAGICE ver. 1

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Threiran, you are right. I missed that text at page 47 about the timing. That sequence is the same as the text I found about turning it off. Bad description about this in the register description though. Very bad description.

indianajones11, no, you are wrong!
First write is ONLY WDCE! See the code again of the first write:

temp = BIT(WDE) | prescaler; //<== Only preload of temp!!!
SetBit(WDTCSR,WDCE); // <== Set WDCE bit ONLY
WDTCSR = temp; //<== Set WDE bit and prescaler bits

This first write results in that the prescaler bits is NOT set!

The correct timing is as described at page 47, that I missed, and is the same as I came up to. However, and this is important, I claim that it is a **** CHIP BUG ***** if it works setting the WDE bit without using the correct timing sequence. This means that the safety of the chip is reduced. It is much worse to set the WDE bit by misstake without setting the prescaler bits than with the prescaler bits as this means running the watchdog with shortest possible time!

The idea with the sequence is to protect enabling it by mistake if the mcu for some reason starts to execute code outside the actual code.

My favorites:
1. My oscilloscope, Yokogawa DLM2024.
2. My soldering iron, Weller WD2M, WMRP+WMRT.
3. JTAGICE3 debugger.