ATTiny watchdog and interrupt I'm trying to control an Arduino Barebone from an arduino with relays.
Basically when the attiny starts it should switch on the arduino for 4 seconds.
The Arduino sends a signal back to a digital pin of the attiny and as long as it is set to high the attiny should leave it working.
If it is low the attiny should switch the relay of.

the problem is some changes to the code make the interrupt reset the attiny (which would switch of the arduino) othertimes- in this case.
the interrupt doesn't work at all.



#include &lt;avr/sleep.h&gt;
#include &lt;avr/wdt.h&gt;
#include &lt;avr/io.h&gt;
#include &lt;avr/interrupt.h&gt;

#ifndef cbi
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &amp;= ~_BV(bit))
#endif
#ifndef sbi
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
#endif

int pinBoard = 0;
bool boardOn = false;
bool startBoard_flag = false;
int pinBoardReturn = 3;

volatile boolean f_wdt = 1;

void setup() {
  cli();//disable interrupts during setup
  pinMode(pinBoard, OUTPUT);
  pinMode(pinBoardReturn, INPUT);
  setup_watchdog(9);
  cbi(ADCSRA, ADEN);                   // switch Analog to Digitalconverter OFF
  // cli();//disable interrupts during setup
  for (int i = 0; i &lt; 10; i++) {
    digitalWrite(pinBoard, HIGH);
    delay(100);
    digitalWrite(pinBoard, LOW);
    delay(100);
  }

  PCMSK |= (1 &lt;&lt; PCINT1); //sbi(PCMSK,INTERRUPTPIN) also works but I think this is more clear // tell pin change mask to listen to pin2 /pb3 //SBI
  GIMSK |= (1 &lt;&lt; PCIE);   // enable PCINT interrupt in the general interrupt mask //SBI

  startBoard();

  DDRB &amp;= ~(1 &lt;&lt; DDB1); //cbi(DDRB, DATADIRECTIONPIN);//  set up as input  - pin2 clear bit  - set to zero
  PORTB |= (1 &lt;&lt; PB1); //cbi(PORTB, PORTPIN);// disable pull-up. hook up pulldown resistor. - set to zero
}


void startBoard() {
  digitalWrite(pinBoard, HIGH);
  boardOn = true;
  startBoard_flag = false;
  cli();                                  // Disable interrupts
  delay(4000);
}

void shutdownBoard() {
  digitalWrite(pinBoard, LOW);
  boardOn = false;
}

void loop() {
  if (f_wdt == 1) { // wait for timed out watchdog / flag is set when a watchdog timeout occurs
    f_wdt = 0;     // reset flag
    if (startBoard_flag) {
      startBoard();
    }
    bool boardReturn = digitalRead(pinBoardReturn);
    if (boardOn &amp;&amp; !boardReturn) {
      shutdownBoard();
    }
    system_sleep();
  }
}

//****************************************************************
// set system into the sleep state
// system wakes up when wtchdog is timed out
void system_sleep() {

  // GIMSK |= _BV(PCIE);                     // Enable Pin Change Interrupts
  // PCMSK |= _BV(PCINT3);                   // Use PB3 as interrupt pin

  set_sleep_mode(SLEEP_MODE_PWR_DOWN);    // replaces above statement
  sleep_enable();                         // Sets the Sleep Enable bit in the MCUCR Register (SE BIT)
  sleep_cpu();                            // sleep

  // PCMSK &amp;= ~_BV(PCINT3);                  // Turn off PB3 as interrupt pin
  sleep_disable();                        // Clear SE bit

  // sei();                                  // Enable interrupts
}

//****************************************************************
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(int ii) {

  byte bb;
  int ww;
  if (ii &gt; 9 ) ii = 9;
  bb = ii &amp; 7;
  if (ii &gt; 7) bb |= (1 &lt;&lt; 5);
  bb |= (1 &lt;&lt; WDCE);
  ww = bb;

  MCUSR &amp;= ~(1 &lt;&lt; WDRF);
  // start timed sequence
  WDTCR  |= (1 &lt;&lt; WDCE) | (1 &lt;&lt; WDE);
  // set new watchdog timeout value
  WDTCR  = bb;
  WDTCR  |= _BV(WDIE);
}
//****************************************************************
// Watchdog Interrupt Service / is executed when  watchdog timed out
ISR(WDT_vect) {
  f_wdt = 1; // set global flag
}

ISR(PCINT_VECTOR) {
  for (int i = 0; i &lt; 4; i++) {
    digitalWrite(pinBoard, HIGH);
    delay(1000);
    digitalWrite(pinBoard, LOW);
    delay(1000);
  }
  startBoard_flag = true;
  f_wdt = 1; // set global flag
}
Disassembling the delay code indicates it uses micros which needs interrupts on to work.

void delay(unsigned long ms)
{
 27a:   cf 92           push    r12
 27c:   df 92           push    r13
 27e:   ef 92           push    r14
 280:   ff 92           push    r15
 282:   cf 93           push    r28
 284:   df 93           push    r29
 286:   6b 01           movw    r12, r22
 288:   7c 01           movw    r14, r24
    uint16_t start = (uint16_t)micros();
 28a:   d3 df           rcall   .-90        ; 0x232 &lt;micros&gt;
 28c:   eb 01           movw    r28, r22

    while (ms &gt; 0) {
 28e:   c1 14           cp  r12, r1
 290:   d1 04           cpc r13, r1
 292:   e1 04           cpc r14, r1
 294:   f1 04           cpc r15, r1
 296:   79 f0           breq    .+30        ; 0x2b6 &lt;delay+0x3c&gt;
        yield();
 298:   ea d0           rcall   .+468       ; 0x46e &lt;yield&gt;
        if (((uint16_t)micros() - start) &gt;= 1000) {
 29a:   cb df           rcall   .-106       ; 0x232 &lt;micros&gt;
 29c:   6c 1b           sub r22, r28
 29e:   7d 0b           sbc r23, r29
 2a0:   68 3e           cpi r22, 0xE8   ; 232
 2a2:   73 40           sbci    r23, 0x03   ; 3
 2a4:   a0 f3           brcs    .-24        ; 0x28e &lt;delay+0x14&gt;
            ms--;
 2a6:   81 e0           ldi r24, 0x01   ; 1
 2a8:   c8 1a           sub r12, r24
 2aa:   d1 08           sbc r13, r1
 2ac:   e1 08           sbc r14, r1
 2ae:   f1 08           sbc r15, r1
            start += 1000;
 2b0:   c8 51           subi    r28, 0x18   ; 24
 2b2:   dc 4f           sbci    r29, 0xFC   ; 252
 2b4:   ec cf           rjmp    .-40        ; 0x28e &lt;delay+0x14&gt;
        }
    }
}
 2b6:   df 91           pop r29
 2b8:   cf 91           pop r28
 2ba:   ff 90           pop r15
 2bc:   ef 90           pop r14
 2be:   df 90           pop r13
 2c0:   cf 90           pop r12
 2c2:   08 95           ret




That appears to confirm that the code in wiring.c is indeed what is being used on the ATtiny85 core:



void delay(unsigned long ms)
{
    uint16_t start = (uint16_t)micros();

    while (ms &gt; 0) {
        yield();
        if (((uint16_t)micros() - start) &gt;= 1000) {
            ms--;
            start += 1000;
        }
    }
}


Turning interrupts off and then doing a delay is a Bad IdeaTM.




  So i would rather have a counter for the watchdog in order to wait for the specified time?


Using the watchdog timer is certainly one way of waiting for 4 seconds.