interrupt timer exception on MKR Zero

Hi,

i got a small problem with my interrupt timer.

my TCC0_Handler() should execute every millisecond, but every 3seconds the timer skips 1 operation.

Tcc* TC0 = (Tcc*) TCC0;
void setup()
{
  REG_GCLK_CLKCTRL = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID_TCC0_TCC1);
  while (GCLK->STATUS.bit.SYNCBUSY);
  TC0->CTRLA.reg &= ~TCC_CTRLA_ENABLE;
  while (TC0->SYNCBUSY.bit.ENABLE);
  TC0->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV16;
  TC0->WAVE.reg |= TCC_WAVE_WAVEGEN_NFRQ;
  while (TC0->SYNCBUSY.bit.WAVE);
  TC0->PER.reg = 3000;
  while (TC0->SYNCBUSY.bit.PER);
  TC0->INTENSET.reg = 0;
  TC0->INTENSET.bit.OVF = 1;
  NVIC_EnableIRQ(TCC0_IRQn);
  TC0->CTRLA.reg |= TCC_CTRLA_ENABLE;
  while (TC0->SYNCBUSY.bit.ENABLE);
}
int xtime = 0;
void TCC0_Handler() //T=1ms
{
  if (TC0->INTFLAG.bit.OVF)
  {
    int ytime = micros();
    if (ytime - xtime > 1005)
    {
      Serial.print(millis());
      Serial.print(' ');
      Serial.println(ytime - xtime);
    }
    xtime = ytime;

    GPS.read();
    TC0->INTFLAG.bit.OVF = 1;
  }
}
millis() / diff.micros
4048 2001
7049 2001
10050 2001
13051 2001
16052 2001
19053 2001
22054 2001
25055 2001
28056 2001
31057 2001
34058 2001
37060 2000
40060 2001
43061 2001
46063 2000
49063 2001

How many milliseconds in one second? If you said 1000, try again.

i dont know what u mean.

the code skips every 3000ms, 1operation with 1000us.

or the operation after 3000ms would take 2000us.

    int ytime = micros();

micros() doesn't return an int.

ok thanks, but that was not the main problem.

Barst:
ok thanks, but that was not the main problem.

You should NOT be using Serial in an ISR.
You should NOT be reading data from the GPS instance without knowing that there is data to read.
You should NOT be reading exactly one character, when there might be 64 characters to read.

There are 1024 ticks of the clock for every change in the output of micros(). If you are assuming that you will get every value from 0 to 1000 when your ISR is called, 1000 times, you are wrong.

ok thanks, my test of the timer cant work.
but the 1ms reading of the gps data is set by adafruit.

Barst:
ok thanks, my test of the timer cant work.

for quick test of your timer:

add

volatile unsigned long xtime = 0;
volatile unsigned long ytime = 0;
volatile unsigned long millis_time = 0;
volatile bool print_time = false;

at the top.

Change the ISR code you posted to something like

void TCC0_Handler() //T=1ms
{
  if (TC0->INTFLAG.bit.OVF)
  {
    ytime = micros();
    if (ytime - xtime > 1005)
    {
     print_time = true;
     millis_time = millis();
    }
    xtime = ytime;

    GPS.read();
    TC0->INTFLAG.bit.OVF = 1;
  }
}

and in loop, add

  if(print_time) {
    Serial.print(millis_time);
    Serial.print(' ');
    Serial.println(ytime - xtime);
    print_time = false;
  }

somewhere near the top.

big thx :wink: