Hello all,
It's my first time here, after spending 2 days trying to generate an interrupt with my watchdog ![]()
I am using a ATtiny25V, clock set to internal 128KHz (I plan on running it on a 2032 coin cell battery).
WDTON fuse is programmed to ensure WD is running at startup and can't be disabled.
And here is my code :
#define F_CPU 128000UL
#include <avr/io.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/power.h>
#include <util/delay.h>
#include <avr/interrupt.h>volatile uint8_t counter = 0;
void set_pins_out(){
DDRB |= ((1 << DDB0) | (1 << DDB1) | (1 << DDB2) | (1 << DDB3) | (1 << DDB4) | (1 << DDB5));
}void set_pins_in(){
DDRB &= (~(1 << DDB0) | ~(1 << DDB1) | ~(1 << DDB2) | ~(1 << DDB3) | ~(1 << DDB4) | ~(1 << DDB5));
}void init_wdt()
{
//Disable interupts
cli();//Just in case...
WDTCR = 0x00;// Start timed sequence to change prescaler value : WDE = 1 & WDCE = 1
WDTCR = (1<<WDE)|(1<<WDCE);// Set prescaler to 8 sec. WDP[3..0] = 1001, and interrupt mode.
WDTCR = (1<<WDIE)|(1<<WDP3)|(1<<WDP0);// Enable interrupts
sei();
}ISR(WDT_vect)
{
// Re-enable WDT interrupt.
WDTCR |= (1<<WDIE);
counter++ ;
}int main(void)
{
uint8_t reset_condition = MCUSR;
MCUSR = 0x00;set_pins_out();
init_wdt();
while(1){
//To Check if reset was caused by WD
PORTB = reset_condition;
_delay_ms(250);if(counter == 65) counter = 0;
PORTB = counter;
_delay_ms(1000);
}
}
I made sure that :
-
WDTON fuse is set correctly
-
Configured the WD properly following the instructions of the datasheet in init_wdt()
-
Enable changes
-
Set timout and WDIE in less than 4 clock cycles
-
Defined a ISR with the propper vector
-
Reset WDIE in the SRI to keep it in interrupt mode
-
Declader the variable used in the ISR as volatile (can't verify if it works since it resets for instance...)
As proof that the WD is set in less than 4 cycles, here is the assembly code :
00000044 <init_wdt>:
}void init_wdt()
{
//Disable interupts
cli();
44: f8 94 cli//Just in case...
WDTCR = 0x00;
46: 11 bc out 0x21, r1 ; 33// Start timed sequence to change prescaler value : WDE = 1 & WDCE = 1
WDTCR = (1<<WDE)|(1<<WDCE);
48: 88 e1 ldi r24, 0x18 ; 24
4a: 81 bd out 0x21, r24 ; 33// Set prescaler to 8 sec. WDP[3..0] = 1001, and interrupt mode.
WDTCR = (1<<WDIE)|(1<<WDP3)|(1<<WDP0);
4c: 81 e6 ldi r24, 0x61 ; 97
4e: 81 bd out 0x21, r24 ; 33// Enable interrupts
sei();
50: 78 94 sei
52: 08 95 ret00000054 <__vector_12>:
}
And despite all my various attempts, the WD resets my ATtiny instead of interrupting. I can see every 8 secs it resets and shows me a MCUSR with the WDRF bit at 1 , and counter is never incremented.
So the timout is working as I want, every 8 secs. , but it resets instead of interrupting.
I tried for many hours, I don't understand what I am missing here ...
I tried running the ATtiny at 1 Mhz and 8 Mhz just in case there was a problem between the WD and 128KHz clock, or with my programmer at low freqs. . I tried disabling the WDTON fuse and enabling the WD in software, I tried adding 2 NOP after setting the timeout and WDIE to wait the end of the 4 cycles before doing anything else ... same result every time.
I don't know what to do anymore...
Thanks for your help !
P.S. : I am programming my ATtiny with a TL866II plus, and testing it on a STK500, because my USB to SERIAL adapter I use with the STK500 doesn't work anymore)