Timer faster than it should be.

Now unless I am mistaken, the following code should print a number which increments by ~1000 every second.

void setup(){
  initTimer();
  Serial.begin(115200);
}

void loop(){
  unsigned long time;
  time = accurateMillis(); //call this instead of millis()
  Serial.println(time);
  delay(1000);
}

//This is the new millis code code:

void initTimer(){
   //TCCR0B = 0; //disable the internal millis(). - will do later.
   //The following does some register configuration.
   //This may seem completely foreign but simply put it makes the timer generate an interrupt every 1ms
   TCCR2B = 0;
   ASSR = 0;
   OCR2A = 249; //(16MHz/64)*0.001seconds - 1 = 249
   TIMSK2 = _BV(OCIE2A); //enable timer interrupt
   TCCR2A = _BV(WGM21); //Set to CTC mode (resets the timer when it reaches OCR2A)
   TCCR2B = _BV(CS22); //use a 1:64 prescaler.
   //End of timer setup.
}

volatile unsigned long timer = 0; //this stores the number of milliseconds since start.
ISR (TIMER2_COMPA_vect){
  timer++; //increment the timer value every 1ms
}

//This function is equivalent to millis() in usage, but doesn't have the jitter.
unsigned long accurateMillis(){
  unsigned long temp;
  byte oldSREG = SREG;
  cli(); //This prevents the timer value changing as we are accessing it.
  temp = timer; //atomically fetch the timer value;
  SREG = oldSREG; //undo the cli() instruction to re-enable the timer.
  return temp; //return the timer value.
}

So why exactly does it increment by ~250000 each second?

Dunno, but the error factor of 250:1 coincides with the value of OCR2A, so perhaps the timer isn't being reset as you intended?

I just played with it a while to get it to work, still trying to figure out why. All I did was change it to fast PWM mode. I didn't mess with the pre-scaler or anything.

void setup(){
  initTimer();
  Serial.begin(115200);
}

void loop(){
  unsigned long time;
  time = accurateMillis(); //call this instead of millis()
  Serial.println(time);
  delay(1000);
}

//This is the new millis code code:

void initTimer(){
   //TCCR0B = 0; //disable the internal millis(). - will do later.
   //The following does some register configuration.
   //This may seem completely foreign but simply put it makes the timer generate an interrupt every 1ms
   OCR2A = 249;
   TIMSK2 = _BV(OCIE2A);
   TCCR2A = _BV(WGM21) | _BV(WGM20); //fast pwm mode (resets the timer when it reaches OCR2A)
   TCCR2B = _BV(CS22) | _BV(WGM22); //use a 1:64 prescaler
   //End of timer setup.
}

volatile unsigned long timer = 0; //this stores the number of milliseconds since start.
ISR (TIMER2_COMPA_vect){
  timer++; //increment the timer value every 1ms
}

//This function is equivalent to millis() in usage, but doesn't have the jitter.
unsigned long accurateMillis(){
  unsigned long temp;
  byte oldSREG = SREG;
  cli(); //This prevents the timer value changing as we are accessing it.
  temp = timer; //atomically fetch the timer value;
  SREG = oldSREG; //undo the cli() instruction to re-enable the timer.
  return temp; //return the timer value.
}

Try the overflow interrupt...

  TIMSK2 = _BV(TOIE2); //enable timer interrupt
...
ISR (TIMER2_OVF_vect){

Overflow doesn't work as the counter never counts past 0xFF.

Fast PWM mode works as expected, so I have no idea why CTC doesn't work. In fact the only way for it to be counting 250x to fast is if the CTC mode is stuck with the top value at 0 - in otherwords it interrupts on every prescaled clock.
I don't quite understand why this doesn't work.

This works...

void setup(){
  initTimer();
  Serial.begin(115200);
}

void loop(){
  Serial.print( OCR2A );
  Serial.write( '\t' );
  unsigned long time;
  time = accurateMillis(); //call this instead of millis()
  Serial.println(time);
  delay(1000);
}

//This is the new millis code code:

void initTimer(){
   //TCCR0B = 0; //disable the internal millis(). - will do later.
   //The following does some register configuration.
   //This may seem completely foreign but simply put it makes the timer generate an interrupt every 1ms
   TCCR2B = 0;
   ASSR = 0;
   TCNT2 = 0;
//   OCR2A = 249; //(16MHz/64)*0.001seconds - 1 = 249
   TIMSK2 = _BV(OCIE2A); //enable timer interrupt
   TCCR2A = _BV(WGM21); //Set to CTC mode (resets the timer when it reaches OCR2A)
   OCR2A = 249; //(16MHz/64)*0.001seconds - 1 = 249
   TCCR2B = _BV(CS22); //use a 1:64 prescaler.
   //End of timer setup.
}

volatile unsigned long timer = 0; //this stores the number of milliseconds since start.
ISR (TIMER2_COMPA_vect){
  timer++; //increment the timer value every 1ms
}

//This function is equivalent to millis() in usage, but doesn't have the jitter.
unsigned long accurateMillis(){
  unsigned long temp;
  byte oldSREG = SREG;
  cli(); //This prevents the timer value changing as we are accessing it.
  temp = timer; //atomically fetch the timer value;
  SREG = oldSREG; //undo the cli() instruction to re-enable the timer.
  return temp; //return the timer value.
}

Output Compare has to be set after the Mode for timer 0 and timer 2.

Weird. That works.
I tried the other code on an Atmega328 and an Atmega162 (not a type) and both exhibit the same behaviour.
Clearly when switching to CTC mode it seems to forget the OCR2A value (but not from the register) until you write it again.

You setup the hardware in completely the wrong order,
it should logically be:

  1. change the mode
  2. write any other registers pertinent to the mode
  3. enable interrupts.

what happened with your original code is that at the start timer2 is
setup in phase-correct PWM mode, in which OCR2A and OCR2B are
double-buffered, so that they update is synchronized to the value of
TCNT2 - this prevents spurious short pulses when they are updated
by analogWrite.

You change the value of OCR2A, but then don't allow enough time for the
timer to pick up this change before changing the mode to one (CTC) that
doesn't use double-buffering. So the value you wrote is stuck in the
double buffer which is thereafter disabled. OCR2A defaults to 0x00,
so your interrupt is firing on every prescaled clock.

So if you had set things up in the logical order (mode, then registers, then
enable interrupts) you avoid the risk of odd edge-conditions like this.

   TCCR2A = _BV(WGM21); // CTC mode
   TCCR2B = _BV(CS22); // use a 1:64 prescaler.
   TCNT2 = 0 ; // wise to force the count value into range
   OCR2A = 250-1 ; // (16MHz/64)*0.001seconds
   TIMSK2 = _BV(OCIE2A); // let interrupts fly only now all is setup

It looks like this problem is largely peculiar to the Arduino IDE. After a reset, the timers are in "Normal" mode, with the OCRnx registers unbuffered; changes to the OCR registers take immediate effect. Under the Arduino IDE, the timers are in a PWM mode, with the OCRnx registers double-buffered when we get control of them; changes to those registers pend until the timer hits one or the other of its limits. Users of some other means of programming an Arduino may never see this problem, whether or not they set the registers in the "logical order." It might come up if a program used a double-buffered PWM mode, and then switched to an unbuffered mode, but that may be an infrequent usage.

Here's a link to a similar discussion among the AVRfreaks, from just a week or two ago: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=139619.

Tests with the original sketch in this thread showed that TCNT2 never varied from zero, consistent with OCR2A being set to 0 in the CTC mode. At the same time, OCR2A reported a value of 249. It looks like the buffered value was reported, while the active value was something different. I don't find this mentioned in the datasheet. It says,

The OCR2x Register access may seem complex, but this is not case. When the double buffering is enabled, the CPU has access to the OCR2x Buffer Register, and if double buffering is disabled the CPU will access the OCR2x directly.

It looks like write access in CTC mode is direct, and read access isn't. I'm inclined to call this an "undocumented feature."

You will (?) find the code for this in the init() function added by the IDE. The source code is available (in fact its part of the IDE).

Mark

I think the line of code I missed was:

TCCR2A = 0;

Before After the TCCR2B = 0; bit. [Edit: I meant after, shush ;)]

I always take the step of putting the registers into a known state before using them, I think this is where it went wrong.

Thanks.

Ah! Now the situation makes perfect sense. The OCR2x register is always double-buffered. The difference is that when a delay is not needed the value is copied immediately. The timer was in Phase Correct PWM mode which delays copying the value. The timer was not running so the OCR value can never be copied. Reading the OCR register returns the value we expect but the working value is wrong.

TCCR2A = 0; ... Before the TCCR2B = 0; bit.

After. If you do that before there is a brief moment when the timer is still running but in either Normal mode or in an undefined mode. In general: Stop the clock (Clock Select = 0). Change the mode. Set the OCR value.

The OCR2x register is always double-buffered. The difference is that when a delay is not needed the value is copied immediately.

That means its sometimes double-buffered and sometimes single-buffered!

The datasheet says this anyway, but doesn't define the behaviour when switching
modes. To quote from section 17.7.2:

However, changing TOP to a value close to BOTTOM when the counter is running
with none or a low prescaler value must be done with care since the CTC mode does not
have the double buffering feature.

And from section 17.7.3:

This feature
is similar to the OC2A toggle in CTC mode, except the double buffer feature of the Output
Compare unit is enabled in the fast PWM mode.

So switch modes, then write registers. It doesn't matter if the clock is running or not
for these purposes. There's no a-priori need to stop the clock to switch modes.