Why is this method-call inside the setup-function called multiple times?

Hi guys,

thanks to everybody who is gonna try to help with this question.
I just don’t get the behaviour of the following code. I am trying to initialize Timer2 within a class, and wrote all necessary instructions into the corresponding method. Then I am calling that method from the setup-function of the arduino-sketch, as it is supposed to be executed once.

Class Header:

#ifndef Blinker_hpp
#define Blinker_hpp

#include "Arduino.h"
#include <stdint.h>
#include <util/atomic.h>
#include <avr/interrupt.h>
#include <avr/io.h>

#define LEDPIN 5

class Blinker {


public:
Blinker();
void initialize();

private:

};

#endif

Class-Source-File:

#include "Blinker.hpp"


Blinker::Blinker(){
}

void Blinker::initialize(){
  ATOMIC_BLOCK(ATOMIC_RESTORESTATE){
          Serial.println("Beginning initialization!");
          TCCR2A |= (1<<WGM21);
          TCCR2A &= ~(1<<WGM20);
          TCCR2B |= (1<<CS22) | (1<<CS21) | (1<<CS20);
          TIMSK2 |= (1<<OCIE2A);
          TCNT2 = 0;
          OCR2A = static_cast<uint8_t>(200);

          Serial.print("TCNT2: "); Serial.println(TCNT2, BIN);
          Serial.print("OCR2A: "); Serial.println(OCR2A, BIN);
          Serial.print("TCCR2A: "); Serial.println(TCCR2A, BIN);
          Serial.print("TCCR2B: "); Serial.println(TCCR2B, BIN);
          Serial.print("TIMSK2: "); Serial.println(TIMSK2, BIN); Serial.println(TIMSK2, BIN);
          Serial.print("TIFR2: "); Serial.println(TIFR2, BIN);
          Serial.print("SREG: "); Serial.println(SREG, BIN);

          Serial.println("Initialization done!");
  }
}

Arduino-Sketch

#include "Blinker.hpp"

Blinker bl;

void setup() {
  cli();
  Serial.begin(230400);
  bl.initialize();
  sei();
}

void loop() {
  cli();
  Serial.println("Looping!");
  sei();
}

The serial monitor continously outputs this:

Beginning initialization!
TCNT2: 101
OCR2A: 11001000
TCCR2A: 10
TCCR2B: 111
TIMSK2: 10
10
TIFR2: 101
SREG: 10
Initialization done!
Looping!
Looping!
Looping!
Looping!
Looping!
Looping!
Looping!
Looping!
Looping!
Looping!
Looping! Beginning initialization!
TCNT2: 101
OCR2A: 11001000
TCCR2A: 10
TCCR2B: 111
TIMSK2: 10
10
TIFR2: 101
SREG: 10
Initialization done!
Looping!
Looping!
Looping!
Looping!
Looping!
Looping!
Looping!
Looping!
Looping!
Looping!
Looping

etc…

Obviously the code within my initialize-function is called multiple times as seen in the output of the serial monitor.

Why is that? What I noticed is that the code is not executed repeatedly if I remove the line

TIMSK2 |= (1<<OCIE2A);

where I enable the Compare Match A Interrupt. So I guess that this behavious is caused by the interrupt being served in some way, which is why I inserted the cli() and sei() instructions.

I would expect that the ATOMIC_BLOCK(ATOMIC_RESTORESTATE) block does not include the Serial.print() lines and I would not expect you to be turning off interrupts round the Serial.print() in the loop() function; why do you think this is required?

Also, I can't see why you are using the ATOMIC_BLOCK(ATOMIC_RESTORESTATE) block since you do not modify the interrupt enable state in the block.

stowite: Also, I can't see why you are using the ATOMIC_BLOCK(ATOMIC_RESTORESTATE) block since you do not modify the interrupt enable state in the block.

That is not what ATOMIC_RESTORESTATE is used for.

Macro ATOMIC_RESTORESTATE

define ATOMIC_RESTORESTATE

This is a possible parameter for ATOMIC_BLOCK. When used, it will cause the ATOMIC_BLOCK to restore the previous state of the SREG register, saved before the Global Interrupt Status flag bit was disabled. The net effect of this is to make the ATOMIC_BLOCK's contents guaranteed atomic, without changing the state of the Global Interrupt Status flag when execution of the block completes.

So this routine could be called regardless of the interrupt enable state. I think it is correct for the timer register manipulations. Including Serial.prints in such a block is a very bad idea.

My guess is that your code is crashing and causing a reset which will re-run setup(). I wonder if this has to do with the code they added in HardwareSerial (see below) that catches someone trying to overflow the output buffer with interrupts disabled.

  // If the output buffer is full, there's nothing for it other than to 
  // wait for the interrupt handler to empty it a bit
  while (i == _tx_buffer_tail) {
    if (bit_is_clear(SREG, SREG_I)) {
      // Interrupts are disabled, so we'll have to poll the data
      // register empty flag ourselves. If it is set, pretend an
      // interrupt has happened and call the handler to free up
      // space for us.
      if(bit_is_set(*_ucsra, UDRE0))
	_tx_udr_empty_irq();
    } else {
      // nop, the interrupt handler will free up space for us
    }
  }